Spring Tips: JPA

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
fans welcome to another installment of spring tips in today's installment we're gonna look at JPA at the java persistence api now DP is a long-standing API it's been around forever in a day and it has certainly enjoyed a lot of use in the spring ecosystem and beyond and particularly its most famous implementation hybrid 8 has a long history with with spring I think one of the really really powerful sort of multiplicative things that allowed spring to to prosper or Yama's death embrace hibernate for example to embrace or um's it did a really good job of managing persistence right time and so hibernate is the thing we're going to use today although jpay itself is a specification and it can be used with a number of different implementations of which hibernate is just one it happens to be the most popular and most pervasive one but it is just one there's others for example like Eclipse link and spring boot itself of course by virtue the fact that it's implementation it's support is based on JPA doesn't really care which implementation you can use Eclipse link for example you could use you know hibernate to view the number of different ones so today though if we're gonna combine ourselves to just using hibernate we're going to build a new application as usual here at start at that spring that IO and we'll call this JPA we're gonna use the my sequel support when use lumba to make short work of some of the tediousness of java we use time leaf and the web support we'll come back to that in a bit we're gonna use JPA naturally and I think for now that will be enough that's enough to to get started we've got Lombok my sequel timely web and JPA well hit generate letter give us a new project which I'll open up in my ID IDE here you a o JK that zip and we're gonna start with a very simple application we're going to map two entities to a table to a database rather and two tables in my database and I've got a database running on my local machine I've got a my sequel instance running on my local machine called CRM it's a schema there's no tables there yet but we're gonna go ahead and use the API to create those instances with Bailey's table so let's do that we have to tell Springs how to connect to the database that's the first thing and this is not any different than you would do with any other JDBC based technology so my beta is Jo q JP a or just straight JDBC I covered JBC my Vedas and Jo Q and other spring tips installments so this should look at this point very familiar so I'm gonna say spring that data source URL and it will be JDBC : my sequel : four slash four slash hostname port which is usually 3306 the name of the schema which is CRM in this case and we're gonna tell my sequel to not use SSL on my local node we need to configure a password I'll be CRM we need to configure a username and of course that'll be username will be a serum as well now granted this should not live in a property file in a real application but um you know for now we're just use it there okay so that's that's the the basic bones of the configuration that we need but we also want to tell JP a to generate the sequel for us so and say yes it'll generate the DDL based the schema tables and so on all the constructs and primary keys etcetera automatically by looking at our our objects now keep in mind you don't want this property in production you should definitely not get this property in production in fact I would normally put this under a separate property file called application - dev for example where dev is the name of a spring profile that you activate only on your local dev machine so if you deploy into production and you don't have you know spring that profiles that active equals dev then it won't get activated right or go a step further and use something like flyweight or liquor base motivates our database migration tools which are purpose-built for managing the evolution of schema and rolling back if necessary all of it are you could use in tandem with this but certainly you wouldn't use this in lieu of that now we're gonna use generates generate GDL we want that we also want to show the sequel that's gonna be output here so GK is just a giant or and it's an object relational mapper and its job is to take our Java objects or JVM objects and to map them to the appropriate constructs in our database layer and when it does that it sometimes it sometimes does a poor job sometimes we have to give it a nudge here a hint there about what to do and we can't know that it's doing a poor job and as we can see the sequel that is generating for example so it's useful to have this statement activated especially in development again these two things might be busy fallaway or development all right all right now we have our application and we're going to manage two types of Records one is called a customer and a customer will be a thing that will you know store the Davis it's a record that's going to manage customer information so class customer and then customers will have a record of their orders how many orders in they've made right and then a signal that these are create entities like so and we'll give each one a primary key value and that's going to be turned into a and by the way this is important notice that I'm being given the choice between using spring datas ID annotation which is useful and a number of different spring data modules now although almost all of them in fact except for JPA so we'll use a pays make sure to do the right thing there when it give both to auto and granting unique IDs right so these are not natural ideas these are just automating our lamenting surrogate IDs and we can use that and that's fine and our customer will now have some fields so I'm gonna say the first field is called order first then the first name rather is going to call the first no and I want to exert control over the column that's used to store this it's caught this data okay so in Java code it's gonna called first but in the sequel schema that we called first name by default it'll just be named after the field and if they had done something like first name then it would have done it would have underscored it they said earlier would have done whatever we had asked did you asked it to do be a strategy but in this case we're just gonna override it on the on the site of the difference okay so there's the first and last names and then of course we want things collection of orders and I'm going to use a set because I don't really care in what order the data is returned just so long as I have a tomato oh you have set now this is a one-to-many collection I'm gonna have one customer and potentially many orders and those orders if you look at the schema are going to be key based on the foreign key in the order table that points to the current customer so we want to join we want to tell the ORM to load the customer and then load all their all the orders and a separate query in one query though and load all the orders by looking for the orders that have the foreign key that has the ID of this customer and sort of two in order to in order to map that and say that this is a one-to-many relationship let's say that all operations should cascade to the subordinate objects here and then we're also gonna say that want to remove the orphan records if there are any so we don't basically we don't want to any extra orders laying around if we should delete the customer right so that's that's there and then we also need to give it a clue as to what join call them to use so when I say join column name equals and I'm gonna say it let's just say that we want the order table to have a foreign key called customer FK okay now this is a another instance you know this remember I'm imagining a product order like an order on a website and that's the that's an interesting table name because order is a reserved keyword in certain dialects of and in certain sequence I like certain in my sequel's dialect right and we don't want to run afoul of the of the parser so I'm gonna rename this table to orders and you know just to be consistent I'll rename this one customers alright so there we are there's our two different records they relate to each other this is a one-to-many relationship you you know you could also do a bi-directional thing you could actually have order have a reference to the customer if you want in this case I don't really need it in this case but it's nice to have we also want to have a excuse that's I think as complicated as we're going to get with this domain excuse mr. Park product code and now our job is to write some data to the database so we're gonna go ahead and use Springs basic JP support before we even get to spring data and some of the more sophisticated support we're gonna use the absolute basic support that's been in spring forever I mean just you know since since JP came out basically circa what is it now when did JP a camera as you know early 2000 okay so that support let's see if JP a applications writer we're just gonna write some data to the database using a I'll call back to the stern here application and runner and when the application starts up will will inject a current entitymanager so these importance in spring spring framework and so on for JPA originates I think if you had to pick one it's a new local entity manager factory team okay so here's the local Energy Manager factory bean and this thing it's been around since Trudeau right right now if you're using spring form of five in mid 2018 thing and you're going to be using the Jaypee 2.1 support you have to have that as a runtime image but um but basically all this is a it's been around for a long time and the the main thing that this does the main thing that this support does is it gives you a entity manager that is aware of spring infrastructure things like transactions and so on and it also gives you a entity manager that is thread safe or rather it's it's a proxy around a number of different entity managers that themselves are thread-local so keep in mind the entity manager per the spec is not thread safe in this this is okay because the specification was written for example for technologies like EJB 3 where the entity manager would be assumed to be injected you write something like this persistence context entity you manager okay and you can by the way this will actually work in spring I don't I don't happen to like this style I tend to use constructor injection so private final like that but the the the style assumes that the containing object is going to ever only be used by one thread well keep in mind that spring objects are single tips there's one instance no matter how many threads so if you keep if you inject a pointer to a service for example that uses and entity manager and you make calls to that service from different threads for example the many different threads being used to service requests arriving at for example a servlet container well each time you make a call to that service you're invoking a method in that service that then invokes the entity manager in that thread in the or you know the original thread as a result you're making concurrent calls than any manager that you shouldn't be doing right remember how EJ bees work EJ bees are pooled you have multiple objects in a pool and the container the application server gets an instance of that bean and lots an instance of that bean for each incoming request and then it destroys that bean or puts it back into the pool and there's this whole passivation an activation lifecycle that you have to be aware of and so on so you go you know in new jeebies they go out otherway to make sure that you can write code that is essentially single threaded even though it has to be used in a multi-threaded world well in spring it's just one bean you just have one object it's multi-threaded it has to be multi-threaded whatever you do in there is multi-threaded and so if you use an entity manager you have to be aware of that until spring actually creates a proxy we give you a proxy of the entity manager that itself then manages a whole pool of entity managers and make sure that there's an entity manager on the current thread on what you're making their request so the result ultimately is that well it just works you can write code that looks exactly what you might have seen in eg b3 circa 2005 but it works right the benefit is that you can just write code and move on so now we have this basic entity manager now we need to use infection we need actually run this code in a transaction right in order for this to work so to use a regular naked entity manager you need a transaction so I'm gonna use I could if I were building a service I could use the add transaction transactional annotation on the service and then all the methods there and would be closed in a transaction whenever you invoke those methods but in order to be able to run multiple things on the same run method I'm gonna demarcate my transaction boundaries manually here using the transaction template ok the transaction template has already been wired up for us it's been configured for us by spring boot and it's been given a pointer to the JPA transaction manager ok JP a transaction manager there we are and this thing is aware of GPA transaction so again that's a implementation of the resource local transaction management facility in JP and this transaction template gives us a unified API that we can use to to start and stop the transactions to work with them and so on so you just basically use the traffic template method called execute and everything inside that gets execute instead of transaction now one thing I should say is that you could also use with JP a you could use JTA the Java transaction ativ the API that is the client side middleware for the X open protocol and I've done another spring tips installment on JTA and I encourage you to check that out and if you use JTA with hibernate and with JP a and with spring well suffice it to say there's a whole galaxy of things that you need to get right and in order to do that right but spring boot spring boot under the head goes out of its way to make that kind of thing work for you so if you look at the JPA auto configuration here hibernate JP a auto configuration you can see that this is going to use the local container entity manager factor beam and it's going to import the hibernate JP a configuration and you can see that this configuration is code that you don't want to write trust me you do not want to write this code this code is code that configures hibernate and it configures the the JP so that it configures a JTA transaction manager based on either the application server environments JDI bound transaction manager and/or user transaction and it then configures the properties that hibernate needs to know about the vendor specific properties that hibernate needs to know about - then delegate to the spring JK transaction manager except of course in websphere where of course things break horribly because Webster's weirder they know all the other app servers so we you know this code knows about all those atrocities and it it makes it work for you so basically you can get you can use this it'll do the right thing for you and if using and and if you want to use JTA as described in that other video you'll you'll you know it'll work it just works right that's um that's code you don't write that trust me nobody else wants to write but it's done for you right now we have this let's just write to date it's very very very simple data to the Davis using the making into the manager API so what I'm going to say I'm going to say TT dot execute right that's actually template and that'll give me an a callback and I callback has an expectation that I return the value in this case I can return null I could actually use the new transaction callback without without result or something like that if I like but here I'm going to just use the the version that takes a return value because I'd rather use a lambda form instead of having to use the anonymous inner class form that the the other variance request now let's read some data today the hard code some users you know I do this a lot so Dave I'd them sire we write some people as customers so Phil - Phil common web and of course mark comma Fisher so there we are we've got some names I'm gonna split the names into it's an array of names there and then I'm gonna map each name into a tuple I'm going to split the name right into two into common into the first and last name and then finally I'll visit the tuple of it visit each tuple and I'm gonna persist the data I'm gonna say this DM that persist new customer and here I've got the customer now this customer needs a constructor and for JP a I want probably I probably want to get errs and setters and equals and hashcode and all that kind of stuff so here I use I make heavy use of Lombok so I'll say at data at all our constructors at no log instructors right and remember you need an order and constructor for JP it doesn't have to be public but you do need alright so this is useful you can actually next to say force equals true and you can do all sorts of you can say access equals a private and then force it was true so you could you could do stuff like that but I don't care you know fine whatever okay good so we got that now and we're gonna save some data now that we've got our constructors the constructor that we get is a it takes an ID for the null for the ID the first name will be of course the first part of the tuple the second name will be the second part of the tuple and then we'll just return a give it a list of rather a set of orders an empty set of orders so there we have our data that was persistent into the Gateway and now we're gonna use the entity manager to create a query so I'm gonna create a query here select C from customer see where what that's it actually we'll just do that and let me say that one a type list of customer data back what I mean by that is that the query method will give us a head query object so here we are customer and with that I'm gonna ask for the result this visit each one that comes back so here's each customer and I want to log out I'm gonna have Lombok synthesize a log4j logger for me as well that's a log info typed query results will be and then here I'm going to use Commons land to log out the information that we get we got feedback because I'm going to do that fair bit for the time that we are spending together looking at different results somebody just say Commons line three I'll bring that in it's the versions already managed for me so I just have to declare it and uh and in the music so I'm gonna say log dot info to string builder dot reflection to string customers all right so there we are we've already got mugged at in for don'twe so we don't need that goodbye alright let's see what we get if we run this code as written our my server I think you're confused too my friend yeah it was done in confused alright so we have some sort of error what is the error Oh zero indexed very good so look at that we've written the data they've written the data we can see that hibernate was a nice enough to to create those tables for us in the last run but we have to add the constraint here so it's still doing some stuff and here's the insert calls into three different inserts and then the query that we just that we just ran and since none of them had any other records we didn't you know we didn't visit any of those records we got the we got everything as we expected so there's the results the first thing in the last name in the empty orders collection all right so that worked out just fine next time what I just fine let's go ahead and now add some orders to to see what we have right to see what we can do with that that nested or that subordinate collection but in order to make working with JP just a little bit easier instead of using the regular entity manager which you know to be fair wasn't so bad we just rejected it and used it life is good in order to make it a little bit easier I like to use spring data repositories okay so I'm gonna create a customer repository that's going to extend the JPA repository and manipulate entity entities of type of customer whose hierarchy isn't type of long now it would be I think it's probably interesting for the audience to know that the JPA repository was the first repository type supported in spring data and it came from a third-party product a community project maintained by what who is now spring data lead all over again okay called Hades hade s and it had a you know it has it had this interface based mechanism for current data all right so that's the Jaypee repository and i can use this to read and write and save and manipulate data so we're gonna do that here let's create another transaction okay I you know I don't care what the status actually and in the status in the ten vector another we're gonna write data to the database we write orders to each for each customer so I'm gonna say let's inject a customer positive right here okay credit the final customer posit or II and that's the constructor very good and now I'm gonna writes our data to the database in there say we turn in old for our status and get all the records so it's a customer positive find all get all the customers back and then from each customer I want to create some more data so I'm going to put some orders I'm gonna say int max equals math dot random times five and we want to turn that into an integer and then test it right so there's our count count of orders and we're gonna say for int I equals zero I is less than count of orders I plus plus and we'll add a record for the customers orders collection giving it a consistent view right so what we're gonna be able to query that later so skew will be skew and missus that I - it's not real you look like but it's fine very good and so now we've got a number of different records each of which is gonna have their own Real ID but they should have okay there should be a common sitting over there and of course we need to save that change to the database I'm going to say I'm going to say the advocate a repository is typically mapped at the aggregate so this order is me is not the aggregate that customer is the aggregate all right and all of this will occur in a transaction so of course we're I to throw an exception here with that poem then even though I've done all this work by that point it would all be rollback you wouldn't see it reflected in these in the database all right now let's go ahead and run this okay looks like it worked very good so we know that's working now let's query the data let's actually interrogate the data some more and see what we get and how we can query it so I looked at I wrote a manual career using the entity manager you said you know the and select C from customer see whatever and the IDE is trying its level headed best to help me here but you know I'm a big believer of not having strings in your code if you can avoid it so I'm gonna use the repository to create a custom finder methods here so the first Finder is gonna be based on the parameter surprising the predicate something to say give me a collection of customers find by first and last string at string l so that'll work that'll give me all the customers by their first name and their last name so let's try that so turn notes and here we're going to say customer posture a find by first and last so Dave sire and never give us a collection of people that match Dave's Dave I'm gonna log out Dave here all right so to string builder that reflection to the string David very good so there we go so that's let's see if that query works as we expected it to and indeed it has there's our there's our different records there so you can see I've got three records here for I've got three Dame's basically because I've run this program multiple times and my sequel has retained the data across those different runs so what I'm going to do is to keep things a little cleaner I'm gonna just say and I say that I want to use the customer repository to delete everything first just a clean up the records here a little bit go ahead and rerun the code all right so there's now just one days on the console right and we have zero orders for this particular one try again try your luck there we go so this and this run there more than one order in the you know attached to that customer now that's a a very automatic sort of convention based query that query that located in the repository here is based on a convention and this is true across all the different spring data projects you can give it a you can create finder methods that go beyond the default support in these common repositories this repository supports finding saving flushing to needing etc deleting back you know whatever is appropriate for the technology at hand and you can create custom fibers you can also of course of course create your own custom finder methods with custom crew you know queer names and so on so five full name string F string hello here I'm gonna use a custom peer in there say select C from customers see where see that first equals F and see that last equals L and I refer have to work spring that it needs to know the name of the parameter so we give it a pram annotation F and L and everything set so let's revisit the same code basically by full name and start breaking this up a little bit here alright then that could again okay so they are the same same results as you'd expect nothing is particularly different here so we have the the ordered a customer and we have the orders and that's working just fine now in this case I've used a custom query you know I want to be able to do more interesting things that don't necessarily map necessarily to the aggregate entities at hand here I might want to do things that are you know that involve derived views of the data right so this case we can use a native query okay this is a feature that's nice in JP is you can actually get access to the full power of sequel it is a little cumbersome and I think this is one of the big drawbacks of using a norm like JP is that you are a long way removed from the native sequel but you can still get there it's just you need to know where to look ok so we're gonna create a report basically when I get a new endpoint that returns the collection of orders a summary about all orders so I'm gonna say order summary ok and order for this to work of course we need a project a type called an order summary so when use something called a projection and the projection is going to be an implementation of an interface that we're going to give to JP and that projection is going to have the counts and the SKU all right so we want to create a collection that uses that and we need to tell hibernate and JPA that this is going to be mapped to a native query and a native query will be resolved by looking for one of the native queries that we've registered with JP a with the name order of acquittal order summary so customer order summary in order for us to have that query we need to registered here on our entity so I'm going to say act names native queries I can have more than one associated with an entity for example at named Nina query not hibernate challenge persistence and the name of the crew will be customer dot order summary and the query itself will be select skew as skew and how I as challenge so again this is important you need to have the aliasing there so that they match with the properties that we get from this accountants the other properties in our projection they're from and it's called orders right when you need the orders group by SKU okay so there's our native query it's it's not it's not easy to get that right I guess that's because it guess okay so we've got now our entity we've got a query let's see if that works it's actually run this query now that's when to see the results there so take one of those custom repository to order summary dot for each summary we want to visit the data that comes back and to the same thing as before to string builder a reflection to string summary already good stuff let's get back in this so that should have given us a proxy but that's not what I want is it we want to look at the data hmm well I guess we'll just have to print it out the old-fashioned way yeah let's just do that okay so let's say summary dot gets Q as summer in dot get count instances all right write that code again all right there you go so you can see that there are three instances of the city of q0 you know three instances of skew one two instances of skew - one instances q3 so that's actually that you know that means that you know you can you can understand the breakdown there right we have a how many you know given the four possible skews or rather five possible skews what what how many instances of each skew exist you know do which customers we didn't look at the customers here we just looked at the summary here using the aggregate function count okay so you can get access to us you can get access to low-level sequel and I think this is one of my favorite features in entirety is to be able to use the low-level sequel engine which is very powerful and have that mapped automatically to these pipes they strongly typed types right this is what we want to happen after all stick it get the work of marshaling whatever comes back from this into a rather from this into a typesafe representation that we can eat okay so now we have a custom query we looked at different queries we looked at named query so we are now in a good place to look at slightly more slightly more advanced use cases let's suppose I wanted to build a web application okay so let's build a web application I've got timely you might recall time uses a view templating engine and I have spring boots start a web on the classpath and so both of these will let me build a web application and then we build a wrist controller that works with this data or not matter rest controller just a regular controller actually a views that would be called the customer controller I'm gonna inject the customer repository here and we'll create an endpoint that has an HTML page with a view of all the data now think about what's happening here I've got that data customers dot you know whatever okay it doesn't matter and the name of the page customers model data turn customers off I've got a view and that view is gonna render and in the view and we'll look at the V in a minute but in the view I'm gonna have all the customer records and each one of those customer records as we seen before also has a collection of orders well and JPA this collection of orders is lazy what you actually have in the resulting runtime application is not a concrete to hatch set but it's a proxied type that comes from the bowels of hibernate we don't need to know what it is or how it works but suffice it to say this is not actually all of the subordinate records you only get the subordinate records if you touch or iterate over those orders so if you just hold on to a pointer to a customer and don't and don't do anything with the orders themselves then no data will be loaded from the database as soon as you start to iterate through those records as I do for example whenever I use the to string builder and that recursively you know it recursively and reflectively descends into the orders collection whenever you start to do that it didn't have to load the data from the database right and in the best case it's just one more extra query in the worst case you get the n plus one problem where you have a single select for each order and that's a whole other topic we could talk about a thousand different things related to query optimization and so on but for our purposes what we need to know is that this is my default lazy and so if you send this customer to another context outside of a current transaction outside of the current running transaction with JPA well then we're gonna run into some trouble if we try and visit any of those orders and so if you imagine we move this customer to a view to be rendered ok and for Narender it we need to be able to make sure that that data gets loaded correctly so here I am doing nothing to take care of those records and I still want to render it in this view and this view I have to create I'll create the view here horse mane resources templates create a new file here called customers that eh - no that's a a view template for time leaf and I am nothing if not lazy my friend so I'm gonna just copy it here okay paste and you can see what's happening here at it's a very simple view it says for each customers see and the customers model attribute print out an h2 element with the first name in the last name and then visit each order and print out the ID and the SKU alright and I suppose we could actually a.m. have some sort of delimiter here I guess let's think about that how would that work style order I can top:1px sell them back David go so now you can see hopefully if I HTML by CSS foo is not so terrible you can see which order you know you can see all the different ores actually each line will be in order side we don't need that at all so let's just leave that is as is and then see what happens if we run this code so this is a spring MVC controller localhost:8080 customers dot view and there we go we can see the ID of this cube and the XS Q itself and we can see how many customers we have in the database so again this is a random random list of orders just to demonstrate the point but um you can see SKU zero isn't there one two three times all right so if we go back to our report here you can see that it says Q zero has three instances so that's working out just fine right we're actually able to look at the data even though we've moved it across a different boundary outside of the transaction the way we're able to do that is that by default spring boots configures the open session and you open entity manager and view pattern so here it's a spring day open API open and view equals true if I set it to false what you might want to do you know you might want to be defensive about what you pass down to the view layer so that by that point you can't they hit the database so if I hit that if I specify that property and set it to be false let's see what happens if I now visit that page go right the big error that we just we were just given is that it's able to lazily initialize a collection of role blah blah blah so it's it's telling me that there's no session opens for it to then materialize that lazy collection of data so you don't you know you should know about this feature it's being configured for you automatically we've automatically spring his ad for the longest time the open entity manager a new filter that's this thing here and spring boot I'm not gonna just configured for you if you wanted there so this has been around forever it's just nice to know that spring food has gone the extra mile to make that available and to make it work for you automatically so that things just work okay all right so now we've got an application it has a endpoint an HTML application HTML view but this is data this is order data and so you might say that this is especially in the world of you know being in compromised by hackers and and we're the finance and all that kinda stuff this kind of stuff is super important it's important that we have the ability to look at the data to be able to see what's happening to it and so for this reason we're gonna use spring datas support for auditing okay we're gonna actually externalize we're going to configure some of the sums of information that we want to be visible in every single record including the data was created they date it was modified and possibly even the user who created and/or modified that that entity so we want to have that visible in order for us to do that we need to say first of all we have to go through and say at naval JP are they and JPA oddity and then for each entity we need to actually configure a number of redundant things things that you would think we could centralize and actually that's what we're going to do is we're gonna centralize all these things that are repeated across the different entities so let's go back down to our entities here the order and the customers and create a map superclass this is a JP isn't it allows you to define things that should be common across given entities in a single place and the new takes just extend them so class let's just call this map auditable base if that's a word and I'm gonna say that we want to apply a jp8 entity listener okay so this is a listener called the auditing and to do this run this is from spring data GPA again we provide the support out of the box you just call back in JPA and when define our ID in a single place you know that all records will have a so we're good are tormenting primary key we want to have a an idea of when the when this record was created I'm gonna create any local date/time field you could also use a m8w till date although I wouldn't it's Java it's 2018 so use the right thing here and we're gonna use the one the last modified date so again local save time modified and we want things created by that's the user and we'll come back to this in a second but it's done it's a string yet it could be a good it could be a complete object that you map to a tape going to an entity in your because you would want but in this case it's gonna be just a string the name of the Creator user and modified by okay so I'm gonna be modifier right so these things have to be provided by this auditing entity listener and this is something that spring data will do for you it looks for those annotations it doesn't matter what you name yeah fields and alternate all that thing is doing it's taking advantage of hooks that you have and you can also use a joint for example pre remove pre persist pretty update pretty destroy post remove all these lifecycle hooks so if you create a method here for avoid post remove get a logger here I get two pictures to do this okay whatever you could log something in there what everyone do any kind of validation so those those things are there for you but I'm gonna just leave that here and now we're going to extend our order and our customer from that site so let's do that where's our types here oh yeah down here extends mapped auditable face and extends mapped ah difficulties and in this case we don't need the ids anymore that'll break our Lombok configuration but the idea by the base class so I'm happy for that let's see ya bye and good bye okay so now let's run the code again okay do we see the data here now it says created and modified so again that's the date and time of the creation of these instances now the creator field and the modifier field then the user name or the thing that we can use to trace who made this change are at the moment absent in order for us to do that in order for us to have that information wait to tell Spinetta where to look for that information right it's any kind of any regular old spring be I'm gonna call it auditor and it has to implement auditor aware and it has to produce the information that's looking for so they can get Kurt auditor and - you know it does nobody then it's empty it's something in it well of course this could be we could use spring security right if I if I had spring security on the con on the classpath I could take the security context dot get you know current context and blah blah and get principal and then stash that there I could return an optional of Java secure your principal wherever you whatever you want to do right whatever whatever your mechanism for tracing users is but in our case I'm just gonna I'm gonna inject the username my local UNIX username so user and I'll inject that into the constructor there's a very simple example very silly but simple as that obviously in a production application this would make very little sense since most code doesn't run yeah most of this most of the time you'll have our friend of front-end website so you want to want to know who the authenticated user is not the they process how much the stuff or the name of the user on the operating system one which under which this application is running so optional of this user alright so there we are so there's my my hard-coded using and password thing this callback is what's important so just implement that callback and tell it where to find the data and let's see what that gets us already but they go at this jail all day long so it's now filling in those fields for us just as we'd hoped okay now this is I think this is good this is a good first step in auditing the data that's it that's it you know high-stakes environment where you need to have a full audit trail on every single change every single mutation to every single entity everywhere in the system if you're in that situation then this may not be enough you might want to see every single change every single record and they both to go to go back in time and see that and so there's a lot of different other use cases for this as well change data capture for dental is another use case where you endo to see the changes to a given entity and then then we pay them later on for example I mean there's a lot of reasons why you might want this and you should have it there's a is it we have to have any community and relational databases are good at this kind of thing so we are gonna use a project called hibernate on bears which is it spelled env ers I'm not sure where that comes from in French on there needs to like it's a preposition to it you know I think I'm not sure what the here but I'm gonna use that okay I'm even thinking of that actually I'm not even sure we don't bail me so whatever we have this preposition we have this word I'm bear I'm bears and that when I go ahead and bring that into the project here and we have a module that a spring that a module that works with our bears okay we're looking for my data and I don't think a lot of people know about this part which is a shame because it's really really useful so all we need to do is we need to tell first of all we need to tell spring and spring that a JP particular where to find the you know where how to configure our repositories with our bears in the mix right so we have trap to override the default that ojp a repository support in the springboard auto-configuration we override it by using the armrest revision repository factory beam and then we have to make our entities auditable so let's go down here to each entity there it is audited where's our order and find it today all right now this is from the hibernate project hibernate on bears and it's a really useful project and it will work with hibernate and we've already got hibernate running so we don't have to do much to get that to work beyond what we have there so let's go ahead and just run this and take a look at the resulting schema and we should actually interrogate the repository to do that in a second but let's just see if it's stuff like everything should be fine okay so you can see that it's done it's done everything as before but it's also clearly these tables called customers AUD customers but of customers AUD and ordered ad and it's great the schema for all that - all right so select all from this buh-buh-bah create table orders of AUD there's another table like read info and we can see that all show tables there we are and so I expect your backed off from orders there's our 11 rows like offerings quarters so we're gonna see it's an interesting formation there but we don't have to worry about it we don't have to we don't have to drill down and find reverse engineer that schema although you definitely show it at some point what we want to do is just use the repository to interact for that data and so that's fairly straightforward we're just gonna go to our repository and extend also another interface a revision repository and that's going to manage entity the type of customer primary keys except long and the type of the revision will be mapped by an integer and with that basic extension in place we can now add one more printout so we we've got we got to make some changes here we've got let's see we've got Dave but we've only we've only changed Dave twice we changed everything else once right we created the record we created we actually modified everything twice so far let's go ahead and now modify Dave just in particular to illustrate the point so I'm gonna find Dave desire to visit Dave is it each record in the collection that comes back and we're gonna change Dave to David I'm not sure that's is I don't know if he appreciates being called David but it will just do it because it's a when is a short name for the other and we're gonna say customer and pops are unsaved Dave and now another transaction I'm gonna get back to each record all right this is of course I'm talking about the good the doctor gave it sire is a friend and a hero so here we go we've got the we've got David I'm gonna get the ID so oh I forgot the map superclass also should have the at that annotation from Lombok to get the getters and setters which makes this easier very good and now I'm going to visit the repository I'm going to say find revision for ID and that's it and then find my provisions for the customer entity whose ID is equal to yes so we can actually simplify that a little bit here and then put each revision that comes back that what we get so log that info vision maybe I get metadata go there with a string vision all right so all I'm doing is I'm putting out the revision metadata for a given entity and we'll see it logged there I'm looking up Dave just a just a DB scale okay let's just put it see what we get cool so there we are we've got three records three provisions here you can see we've got ID five and here's the different dates right 8:26 well these are all basically the same time I want to click it actually yeah let's um introduce a pause alright this entry to pause here two seconds sleep there we are okay there we go so we can see that the second change happened at thirty three seconds after and third change captain at thirty five seconds after so we can see the data there and also you can see the changes look at that you can see here's the first instance of that record called Dave and there were zero orders here's the second to that record called Dave and here are all the orders here's the third instance of that record for David not Dave the same number order so he can see the associated entity and the time when those changes happened so I think if you need that kind of thing it's very very powerful now I did it I just slapped at audited on all the entities in my application naturally you may not want that for everybody in here all good crap and you don't need to write you can use at audited on the entity that you care about the ones that you want to be audited and you can also then exclude other entities from that for example but if you do have an entity that references another one for example in this case the customer reference is over the orders then they both need audited or you need to exclude it right tonight so if you do that it's out of the field here then it'll exclude that from the auditing it won't change it won't capture the revisions to that subordinate collection they're referred it captured in this case alright so we've looked at GPA GPA of course is a trustworthy technology that's been around for a long time I think that for a lot of people JPA is gonna be you know it's gonna be a very convenient fit it lets you work with objects and if you're just trying to get a few objects in your domain model persisted into a database and you don't mind giving up some control over the queries then you should you should take a look at the APA there's some really good advice out there on on how to improve JP performance for example so hyper systems giving a shout out here to my my friend Vlad's amazing book so if you get a chance maybe read this this book you can buy it here too high persistence that I owe it's run it's written by glad me how see ya I'm not even I I don't want to butcher his name but he's a developer advocate he's a developer advocate for the hibernate team and you know he he's got some very good examples on how to make hibernate absolutely scream in terms of speed you know so I definitely recommend that I think the most powerful part of your already BMS is sequel right so I don't want to give up sequel I don't want to have control I want to lose that control and so you should be aware of these little opportunities to regain that control it's nice to have your objects mapped nicely to a to the different structures in your database but that shouldn't mean that you lose control and so it's very important to keep keep in mind what's happening behind the scenes that's why one of the first things I did was to illustrate all the different sequel statements at RA that are executing here when we run this code now keep in mind it's not actually that in performant to run a lot of sequel statements especially if you're doing it in a batch inside of a transaction it's in performance equate if each one of these sequel queries was a separate transaction that would be very very slow but to run in three or four sequel statements in a single transaction that it's it's painless you know we have looked at the absolute basics of JPA I didn't look at any any particular specific features of our implementation we didn't spend a lot of time looking at mapping there's a you know there's billions of pages I'm sure on how to map entities to other types of entities I did a slightly more interesting example here with a map superclass and a one-to-many relationship but there's a whole number of other things you can do here obviously I hope you will pursue that at your leisure and we looked at some of the things that could be considered anti-patterns like this open entity manager and view thing some people really don't like that and actually spring boot I think it will log it out won't it let's see schooling well I think it's not foreign is it yeah it actually does look at that so spring JPA open and view is enabled by default therefore database queries maybe four maybe perform during view rendering explicitly configure about a lot to disable this morning so again if you don't want that um you know it's nice to know about it so has to have it if you need it and then if you're just trying to get enough an application up and running as quick as possible as we did here then that's the that's the tool for you what advice you might wanna get rid of it and you know your mileage may vary when you start moving these wires over rest api and so on so you have to have to care about that you have to care about what happens there with that my friends I thank you for watching and I hope you got something out of this and we'll see you next time you
Info
Channel: SpringDeveloper
Views: 14,687
Rating: undefined out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud
Id: 2E8_0Qxi6Tg
Channel Id: undefined
Length: 62min 0sec (3720 seconds)
Published: Wed Oct 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.