Domain-Driven Design with Relational Databases Using Spring Data JDBC

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to the session nice to see that people go to sessions that are actually important like stuff like JDBC and not that just the stuff that is fun and new and hip because I think like somewhere in the last days I heard a statistic sly that 80% of the downloads that start out Spring dot IO actually contain a JDBC driver so pretty much everybody still uses this stuff anyway before getting into to the meat of the talk I like to tell you a little story it's quite some time ago about 30 years damn that's that's scary I was still going to school in America it probably would have been high school and a friend of mine approached me at school and asked me if I could help him because after school he planned to pick up a sofa I thought well yeah sure why not drive to the shop get that sofa get it to his place then go back to my place takes maybe one or two hours extra shouldn't be a problem right well we get in his car we start driving driving driving and after like two hours I start wondering like where the heck is this shop where you want to get that sofa it turns out it wasn't that far anymore it was like another half hour pick up the sofa pay for it get it into the car took maybe another hour get it to his place another two and a half hours and then get finally to my place back home was like I don't know the total of six or seven hours it was really late when I arrived at home interestingly I can't remember that my parents reacted to that in any way at all seemed pretty normal to them I think know what to make out of that well the whole thing is kind of a fun story we like to remember it's we talked about it if we meet again and I guess it actually strengthened our friendship like having experiences together right of course that would have changed if a thing like that would happen like every other day it would probably have pretty much destroyed the friendship really really fast what does that have to do with my talk you'll see let's first talk about relational databases relational databases are awesome the first one popped up in the 70s so they're like what 40 years old over 40 years old almost as old as I am and as just mentioned they are still used by many many people which makes you wonder why I mean this whole no sequel stuff got lots of attention and of course they get used as well but compared to relational databases they are still niche why a relational database is so prominent in our industry I think there are multiple reasons one is they are like the DRI principle built into code every piece of information by design has a single place to be in a relational database relational databases have strong consistency guarantees you can put constraints on your columns that make sure that certain values will never ever be null or check constraints that they adhere to assert certain regular expression and probably most powerful foreign keys that guarantee that if you reference a row in another table that row will actually exist and can't go away if anybody of you ever tried to build that menu without a relational database like into an application he probably created lots of bugs or used a lot of brainpower to get that right so it's really nice to have that built into the database right and the reason why this works so well at least in my opinion is that relational databases have a solid foundation in mathematics there are actually things that are proven about these things and don't get me wrong I like mathematics I actually studied physics which is basically mathematics with add-ons but I still don't want to deal with mathematics every every day at work when I'm coding and you don't have to but the fact that these things are proven and based in mathematics this leads to really solid abstractions that don't only work most of the time but that actually work all of the time and I think we know a lot of applications a lot of libraries that present us with some kind of abstractions that aren't found it in mathematics at all and they typically are very very leaky abstractions a you start out and use it and everything is nice and then suddenly you see corner cases where stuff behaves just weird you hardly see that with databases and then we have sequel again sequel a child of the 70s kind of ugly coming from a time where people thought that programming languages should be readable just like English but at the same time obviously weren't totally not capable of creating such a language so they created stuff like sequel which contains a lot of English words but doesn't read at all as like English but sequel is immensely powerful I don't know many people probably just use if at all insert update delete and select statements with where clause maybe with the group by but if you get into the details of sequel starting with having with NL analytic functions you'll soon realize that sequel is immensely powerful actually current sequel dialects at your incomplete you can do literally everything with sequel they don't really do that I mean you probably could write your next web application completely in sequel alone but that probably still isn't a good idea but you have this power and actually it's fairly often not used at all and with all these things we build stuff like this schemas most of the time probably more than six tables maybe sixty maybe six hundred or maybe even six thousand and they work kind of actually they work perfectly but they still have problems despite all these great features of relational databases there are problems with those and many of those scare go down to scalability and then any database and administrators in the audience Oh in the first row that's going to be dangerous they don't like to be told that their kids their databases actually aren't that scalable and that fast all the time it already starts with like I had a big discussion a long time ago with a DBA of my project about the performance of the database and he was like you can't get faster than a relational database and that if you think about it that's obviously stupid if you just need data and you have that data in a flat file in exactly the format you need nothing is going to be faster than just reading in this flat file if you have any additional structure in there it will cost you performance but of course you do get a lot of stuff for that like all the flexibility to sort it whatever way you want to have all these different careers if you want to build that's based on a flat file then you are for certain better off with a database or a relational one one thing that limit scalability are locks especially in the relation with this constraints I mentioned before if you have a foreign key constraint between two tables and you want to insert row in the first table which references the row in the second table you need a lock on that reference row on the second table because otherwise the database would check that the row is there insert the new row and somebody else in the meantime deletes the other row that you just checked is there you don't want that to happen so you need some kind of locks there and locks always limit scalability but even if locks don't create a problem for you the sheer resource use of check in foreign constraints might the foreign constraint if you like do normal basic crud stuff you hardly think about putting a foreign constraint in or not if you need it from a domain perspective you probably do but they don't come for free again if you want to insert a row that reference another row the database first has to find this other rule it basically has to perform a signal statement most of the time that will be just an excess by index so it will be really really fast but if you do millions or even billions of inserts this going to be a is going to add up and in many batch process you end up with disabling on keys and then maybe at least for me most important what is if you want to scale above a single server if you're a single server doesn't fit your needs anymore for one reason or another many databases have features that you can access tables in a different database just the way you can access tables in your own database they look completely the same which is nice exactly in the same sense as it was nice when my friend asked me to pick up that sofa because now you have a table in your schema that you might want to join with but suddenly this join will take orders of magnitudes more time and resources where as if the table is actually in your database and you don't see the difference I'm not complaining about that accessing a different database is slow it is bound to be slow it goes across the network the problem is when you don't see this stuff anymore this trips you up as a developer and causes performance problems or even bugs so these are kind of problems inside the database but it gets even worse once you try to get data into your actually app application assuming that you don't write your application in in a turing-complete sequel dialect you probably want your data from the database into a Java or Kotlin or whatever application and then it's going to get funny Ted nuit coined the phrase that object relational mapping is basically the Vietnam of computer science and we're going to see why this is the case who here has tried to ride his or her own object relational mapper there are still a few hands a pretty young audience I guess back in the time before we had hibernate we had many object relational methods or differently and they basically all had only one thing in common they sucked this led many teams and many single developers to think well it can't be that hard I create my own object relational mapper which obviously resulted in even worse implementations of that pattern so what is the problem why is this so hard you start easy you think well I have entities in my domain and these obviously map to tables right that's straightforward and then I have properties in my classes and these map to columns this is simple right we are almost done all we now have to do is map references references are obviously foreign keys but if you look at a real schema like not a tiny one like the one I just showed you a couple of slides ago but a real one with 60 or 600 tables chances are they are all connected and if you want to load a customer which has orders you very often probably don't need the orders so you come up with something like lazy loading you load the customer and the customer is some kind of proxy whatever that basically looks like it gonna contain the orders but it actually doesn't and it will fetch it for you once you access it which creates two problems one is a minor one and might actually be removed if you choose a different way to implement your object relational mapper than hibernate and JPA does which are lazy loading exceptions the context where you loaded your original object is just done and if you now try to load the rest of your object you get an exception that's kind of okay because it's hard to Masonic an exception I mean I've seen application of catch runtime exception and then empty curly braces but we don't do that right so we will notice the exception we can fix the problem but there's another kind of problem which is again the sofa problem we access the collection of orders which looks like a tiny dereferencing in the JVM which should be done in a couple of nanoseconds but what really is happening is our object relational mapper is creating a sequel statement sending that sequel statement over the day wire to a database the database is processing that sequel statement coming up with the result sending it back and this might take what a millisecond 10 milliseconds again a millisecond doesn't sound that bad right but it's a thousand times slower than accessing something in local memory and I've seen people bitten by that over and over again in projects where stuff was just fine in the test environment and then suddenly got horribly horribly snow in production where the number of rows was just way bigger than everything they had in tests so we do eager loading right lazy loading is kind of stupid we learned we do eager loading and that is actually great you get your first object from the database then you wait like five to ten minutes and then you have your complete database in main memory you're laughing that's actually a great state to be in because now everything is going to be really really fast because you're only accessing stuff in your local memory you probably should make sure that from time to time you actually write your changes to the database because otherwise somebody's getting really really angry with you once the power goes down or something but it's a great state to be in sorry unfortunately some people house have so much data that it just doesn't fit into main memory so what are they supposed to do well nowadays if you do Java you probably just use JPA which is great because you have the option to either use lazy loading all you use eager loading which means you can have lazy loading exceptions you can have the sofa problem and you can have your main memory filled up with stuff that you don't need all at the same time that's great right well no it isn't and at that point we are just talking about reading stuff right what is if we you want to possess stuff or delete stuff maybe as an example take deleting if I delete an order I probably want to delete the other items right or items without an order probably doesn't make sense I probably don't want to delete the product the order was referencing to because my somebody else might still want to buy that just because I don't want to buy it doesn't mean you won't mind so this led in in JPA hibernate to all these cascade stuff where you can actually have different cascading behavior for persisting stuff and deleting stuff and loading stuff which is a really fun way to make really complex problems with really weird behavior like something works and something that looks like almost exactly the same doesn't work at all and throws exceptions that give you if you are at least not very experienced no hint at all what is going on and what is not working so this doesn't feel really good another example which is basically the same problem is that of optimistic locking many many people use optimistic locking right you have an additional column in your database typically cold version and whenever you read it you read that version with everything else and if you write to the database you do two things you increment that version basically as a marker okay I changed this data and also in the update you compare the version that you have in main memory to the version that is right now in the database and if that doesn't fit it means somebody else access that row and change that row in the meantime and in order to be sure that all your business decisions that you made in the meantime time makes sense you better start over and to help you with that you get an optimistic locking extension which is great that's the way it's supposed to be but now look at an order again let's assume I have a process that processes the payment I received two orders and checks like okay I received this payment from this customer and I have this open order by the same person and I checked the value of the order against the value of the payment and if they match up I mark the order as paid and I update the database in the meantime another process maybe the customer itself goes in and adds 25 line items to the order 25 MacBook Pro fully loaded and I just marked that order as fully paid because when he adds a road to the order item table does the version in the order get update it does it in hibernate okay nobody seems to know so you don't use happenes right who is using hibernate okay and you don't know that stuff that's kind of scary isn't it actually I don't know either I'm pretty sure there's a way to configure that but and I think the default is no diversion doesn't get updated in the order but again there's something that can really easily go really badly wrong and a roomful of hibernate developers don't know how it behaves that is kind of scary let's get away from the scary stuff let's go back to fun stuff whoever wrote integration tests with databases okay that's not everybody but plenty who enjoyed that I know that's the pervert I'm allowed to say that he's basically my team lead so that's okay well what is the problem the problem again is the schema that is like connected all over the place you want you to write an integration test that does something with orders let's see but the orders reference product so you need a product and the product has a prototype so when you need a product type and product type has a main responsible person for marketing so you need that person and such a person has a boss so you need a boss person and you end up with creating dozens of rows in your database in all different tables although you really just want to look at the order and your item that really doesn't feel right right and actually there's a solution and that solution I almost assume many people here have read about that probably about ten years ago or something it's domain-driven design in the book domain-driven design by Eric Evans they want to take a foot of the previous slide I can do that for you but now you have to treat it right okay in this book he describes the concept of an aggregate and aggregate is in cluster of objects that belong together that are used as a single entity basically the entity now in a single unit and if that if we apply that concept to our little schema it might look like this it's perfectly fine to have aggregates that consists just of a single entity but many will contain a few if you have many entities in one egg regret you are probably doing something wrong and every aggregate has one special entity that is the aggregate root marked it like this and the aggregates that consists just of a single entity the choice is pretty obvious in cases where multiple entities there's often like if you think like how would I name the aggregate there is normally an entity in there that has exactly that name and that normally becomes the aggregate root of that aggregate and the purpose of the aggregate aggregate root is to be a handle for that aggregate everything outside an aggregate can always only reference the aggregate root never ever anything inside this especially means like in the example of the legal model we don't hand out the list of contents and hand it to something else in our application so it can add or remove stuff in there this is not going to happen instead it has to call a method on the aggregate root and the aggregate root does all the changes it needs it might be just adding or removing a row in that collection but maybe it has other constraints maybe all the bricks that appear and the content also have to appear in some way in the menu so the aggregate root can verify that and then there's one more rule about aggregates is aggregates are always consistent strong transactional consistency which means an aggregate is always in a consistent state except when I'm in the middle of a method of the aggregate root whenever I'm outside the aggregate is consistent and since it's a unit I always handle it as a unit I store it as a unit I load it as a unit it's always consistent in the database as well but across aggregates I only have eventual consistency and that's again a part I have to I'm a little scared of the database administrator guys because that means we just lose all the foreign keys because otherwise we can't have eventual consistency right but being with me we still have a problem how do we build eventual consistency in our java model how is that going to look like if I have a product that reference or an order that reference a product the product has to be there I have to have the a Java object right but hey we are to spring conference so the solution is obviously annotations well annotations are great probably the best addition to the java language ever but actually in this case we have a much easier much simpler solution and the solution is just don't use references if you reference something in a different era --get which then has to be an aggregate root because we are not allowed to reference anything else we just reference it by ID and that's basically it it really sounds simple but it's an immensely great idea all the problems or almost all the problems suddenly just go away everything just becomes a piece of cake loading persisting deleting we just said an aggregate is one unit we always handle it as a unit we only it has to be always consistent that means if I have an aggregate of an order in order to be consistent it has to have all the order items that means if I load it from the database I always load it with everything that belongs to that aggregate and that's limited because it's an aggregate it's not everything if I delete it I delete everything if I delete an order I delete all the other items but I'd only delete the customer and the product the stuff that is outside that is in different aggregates optimistic locking again the unit is the aggregate represented by the aggregate root so I have only a version attribute in the aggregate root and when I whenever I update an aggregate I add I update that version attribute of the aggregate root problem solved the scenario I just described with order and order item doesn't happen because they all go through the aggregate root integration tests well we dropped all the foreign keys I'm always looking at you he's still smiling but I don't know if it's like a mean smiling still looks friendly we don't have any foreign keys anymore so if I want to write an integration test with an order and order items I can just reference the products 47 11 23 and 42 and nobody cares because my integration test doesn't care by definition I want to test order and other items and the database doesn't care either anymore because it doesn't have any foreign keys anymore I mean not across aggregates inside aggregates we still have foreign keys also for people like me things get easier because I now don't need to support m2 m1 or m2 any relationships which is really really great because these are really really hard why don't I have to support those because those if you think about it are always references across aggregates if many things reference a single one if that is not a different aggregate then it has to be inside one of those M things that is referencing it but then the other things are referencing something something inside a different aggregate which can't be so M to 1 and M to n relationships are always references across aggregates and we don't have those anymore well we don't have those on the Java side on the Java side they are just IDs in the database we still have these references just as normal foreign keys the schema looks exactly the same the only difference is that we now make a clear boundary like what does belong to this aggregate and what belong to the to a different aggregate including in the case of M to n relationship which I like have an M to end table like this mapping table in between which kind of in the database world view doesn't belong to either table in our new view of aggregates it straight really strictly belongs to one of the aggregates and these choices have a lot of benefits and they kind of hinge at these foreign keys in many cases because we have options here we can do what I just described and just drop them which allows us to even to split aggregates on a to divide different aggregates and put them in different systems they don't even have to be all relational we can have the one kind of aggregate he'll be in a relational database and then put a different aggregate a different kind of aggregate maybe in a neo4j a graph database or a database whatever fits the kind of aggregate we are dealing with and it doesn't make any difference on the Java side because we are just dealing with IDs and pretty much every kind of database no matter how weird and no sequel it is probably can access elements things by ID otherwise I would get really skeptical about that rule so we can completely split stuff up which should should sound nice for everybody who is riding the microservice train like where everything is nicely cut into vertical slices you can do that perfectly fine with that but many people probably kind of miss the foreign keys so it could use deferred constraints because actually we we use this eventual consistency between aggregates just as a tool to arrive at the idea at the option to use IDs to reference different aggregates there's really nothing in there that forces us to really make this eventual consistent so we can play with that and one way our deferred constraints for those that don't know before deferred constraints behave almost exactly like normal constraints with the single exceptions that they are aren't checked on every data manipulation language statement so not after every insert or update but only when a commit is issued which is great for integration tests because an integration test at least if you do them the typical way it is basically prescribed or recommended by the Spring Framework you actually don't do a commit at the end you just create your data perform your action that you want to test assert the result and then you make a rollback so you have the constraints in your database which get checked at commit time which is important for production but for tests they are basically irrelevant and you still can reference the product 47 11 23 and 40 - no matter if it actually exists in the database or not or if you have a really conservative database administrator you still can use normal constraints because again there isn't really a real requirement to get away with the foreign keys it was just an intermediate step for us to help think about the problem and even if you have normal constraints now your database looks as it is right now exactly the same without any changes so one might wonder what have I gained now I have all the IDS in my java code instead of easy-to-use references and I need to dereference the IDS using a repository or something which is certainly an extra step and kind of annoying but I got a lot of flexibility at any point in time can go back to the other options I just presented and pull stuff out put it in a different application in a different system even if I don't do that suddenly these borders between things become obvious which is nothing else then modular blah breaking your application in modules which panas recommended to do as a good thing again I think in the 70s and so far I don't think anybody came up with a good argument against that if you now have these aggregates the next good thing to do would be to put them in packages every aggregate gets its own package and if you then apply a little rule that you don't have cyclic dependencies between packages you get a real strong structure for your application it will feel painful at the beginning can almost promise that if you never work this way it is kind of irritating but it really helps because people have to think about where stuff belongs and this alone is I think a great benefit so we talked about relational database we talked about domain driven design I guess it's time to talk a little bit about spring data JDBC what does that have to do with all this well you probably guessed it spring data JDBC forces you to do exactly as I just described spring later JDBC one of its key strengths in my personal opinion is it does not support M to 1 and M to n relationships other than using IDs it forces you to think about your aggregates otherwise you get will get in problems really really fast and really really obvious and again I think that's a good thing the sofa problem is so bad because you don't notice it until it causes really serious problems and you're in production with an application that doesn't perform instead I'm very much prefer library a framework that basically smacks you on your fingers when you do something that it considers a bad idea and this is what spring dated JDBC does so let's take a look our code the spring data JDBC actually looks like I try to make it a habit not to do live coding in presentations because I'm not just long and watching me - code is actually rather painful and nobody really deserves that so what I have here is basically the domain model for the diagram that I showed multiple times during the talk one of the simple entities the aggregates that just consists of a single entity was the brick and the brick might look like this one it's a simple class simple as it can get it doesn't even have to have getters and setters you can have them and spring data will use them if they are there but you can use plain fields if you want as you can see here you can have non default constructors if you're the names of the constructor map two field names spring data will be happy to use them you could even make this immutable and have all the fields be final in that case you would need to provide a constructor with all the arguments obviously and you also would need in the Java version with us I don't know a better name for those basically setters that don't return void but a new instance of the immutable class spring data JDBC can use those as well what's their question builders are right now not supported but what should work another thing is cuddling cuddling data classes they do work as well and really the only thing that is an ting at this being a spring data JDBC entity is the ID annotation all aggregate routes need an ID annotation because we need an ID another possibly important thing is if you have maybe a project where you still have JPA in there this obviously is the ID annotation from spring data and basically if you work with with spring data JDBC and UC Java expositions in your imports something probably went wrong and it won't work and that import is probably the reason so there's really not much to talk about those of you that ever used spring data probably know how to create repositories simply by extending the current repository it takes to type to type arguments first the aggregate roots type and second the ID type of that aggregate root and it will provide various methods for you that we can actually look at and here for example you get the safe all methods also safe a single entity count all entities check if an entity exists and of course deleting entities more interesting is the legal model the legal model starts out just as simple as the brick with an ID it has some more attributes which are supported straightforward slightly more interesting might be the list of manuals it's just list the manual again is an entity which means a simple Java class and it doesn't even have an ID because if the legal model reference the manual that this indicates that the menu is part of the legal model aggregate so basically the ID of the menu becomes the ID of the legal model it belongs to plus the index in list the same applies for if you have maps in there instead of the index of the list you now have the key of a map [Music] it depends so the question sorry the question was is this a value object that's actually a tricky question it depends on the real exact definition that you use for value object you actually could make it like immutable and have an equals and hashcode and everything and in that sense it would be a value object but it really does have an ID inside the database it's just that this ID is no longer visible and necessary in Java and in that sense it's really more an entity okay so the really interesting stuff then happens with the content if you remember the diagram the content reference is bricks and bricks are a different aggregate so now we get the situation where we have to use IDs and the way that works is we actually have an ADD method here to add bricks to the legal model it doesn't have to be add whatever you name this method it's just a plain method spring data JDBC doesn't care about it at all the point just is we take proper brick objects here but we just use them to extract the ID and create brick content item objects out of it and these are just simple entities just as the menu that we just saw they have just this one kind of special brick ID attribute that reference is a brick and that's it and we can use that again in the tests up here we create our bricks we save them and in this case it's actually important that we save it them before we use them in the legal model because the way it is set up in this case is the IDS get generated by the database so if I just create the bricks up here they don't have IDs yet so if I add them to a legal model and try to extract the ID I will get wrong I will run into problems so I have to save them at that point they will have IDs I can use them in legal model I add them and I save them and all this actually does work and store data stores data in the database one moment so here you have all the insert statement it does all the inserts on the brakes then in the lego model and then an insert into content which should look exactly as one expect sorry here was a question yeah that's pretty much similar just as JPA we have a default which Maps basically attribute names to column names one-to-one and kennel case gets converted to snake case like underscores there's a naming strategy to change that like all over the place and you also have column annotations to change that in like a single forcing Li attribute and there are table annotations and all kinds of stuff that I don't have time to talk about in detail and that's already what I wanted to show you as far as code goes I'm saying No what's the water so we looked at code if you think what I told you is a good idea no matter if you think you like spring data JDBC don't want to use it or not there are a couple of resources that I would like to recommend to you first three articles it's basically one article in three pieces by von vennen where it talks about how to like how to decide what is an aggregate and what is the separate aggregate in great detail lots of good ideas and advice in there if you actually are interested in spring data JDBC you of course can always approach me but there are a couple of things you probably want to look at on the top right is the talk I gave about it last year at spring one and then there are two articles basically doing a basic introduction and of course there's reference documentation and more and more Stack Overflow questions and then finally if you still want to use the APA or maybe still have to use JPA there's this great article which disgusts again basically similar stuff that I just told you but also describes what hoops you have to jump through in order to make it somehow work more or less in JPA and it ends in recommending its own persistence framework which you might want might be interested in if you're using Scala that's probably not that many people and finally that's me if you want to contact me or if you want to talk to me about stuff other than software development stuff I do I work for pivotal as part of the spring data team and our responsible for spring later JDBC and spring later JPA so I have to use and just as a reminder thinking aggregates I think even if you don't if you still use normal references if you still use JPA but get in the habit to think about where are your aggregates in your domain model I think it will help you understanding how your application is connected and if you have to do any refactoring moving to micro services or anything need to break it up boundaries it's probably a really bad idea to split anything like across a single aggregate you probably want to avoid that which is hard if you don't know where your aggregates are and with that I'm done just disclaimers the sources for all the nice images and that's it time for questions so there's one okay that was actually more than a question it was a statement in a question the first statement is I said that JPA is a thing of a past everybody use spring NATO JDBC and the question was how about abstracting out with different databases how does bring NATO JDBC does that first the statement that's not exactly what I just said and I mean I'd actually do think spring data JDBC is the concept so better solution but it also is rather new and there are some interesting stuff that is still missing so yeah people start using it in production successfully I'm not saying you should like migrate your 10 years legacy application tomorrow to spring later JDBC that's probably not going to be fun for the question about abstracting of databases where we provide the repository and the repository like the the API is totally database independent we support my sequel Postgres I think h2 is the memory in-memory data database we use there's like one important thing like that you probably use will use a lot where you have a map set in your repository and annotate it with a Korean annotation that is actually data specific sequel so if you stick to a standard subset of sequel it would be database independent but you probably will really easy end up with database specific code which again in my opinion is most of the time not that much of a problem of course it is a problem for people that create applications that need to be deployed by different customers that then provide their database but again this is also something that we plan to improve on so that you can store your statements externally and have that database independent but you will still have to like do the conversion if you have like two databases that require different kind of sequel you still have to write both sequel statements okay they okay so the question was the aggregate route has an ID but all the children inside the aggregate don't have an ID and how does the database like if you have an ID ID column in the database how does that fit and the answer is you can still have an ID column in the other entities it's just basically waste you don't need that and you have a primary key or you can have if like the the way it is basically I would recommend to do it within an aggregate the elements inside an aggregate heaven either as a primary key the same value as the aggregate route in case of a one-to-one relationship or they have the ID of the aggregate root plus an additional column or if you have deeper nested elements multiple additional columns that together make up a primary key and that is used by spring data JDBC if you want to provide an ID anywhere that is used as well and should just work okay well you basically you still can have a normal foreign key in the database the key is only to like really separate the aggregates and that's why I basically introduced it over like let's throw the foreign Keys away and look what happens then but you still can have the foreign keys it's just that you might lose some of the benefits for example integrate if you like have a full foreign keys between aggregates you still have again your problems with the integration test right so that's the typical trade-off but now you you basically have the option and you have some some arguments for and against foreign keys that you can evaluate yourself and decide what is best for you exactly there's no right now you have to create your tables yourself I did that here with a schema sequel probably in production you want to use fly base or liquid base or something similar okay to repeat the question does spring data JDBC create tables for you answer no it doesn't so the question is I think basically is how about things that you would njp a model as by direct relationships right it's the way it is modeled right now the legal set reference for example and an age group and what is if I want to find all Lego set for given age group like go the other way and the answer is simple right you query for that just have your brick repository have a methods get me all LEGO sets for a given age group it should be really easy to do it's just the only thing is you have to to create the query itself oh you're yourself well if you if you look at it at the example or the question was I stated m to 1 and M to n relationships aren't supported the answer I showed you in the example the Lego set references or the the content references bricks so that's basically a many to one relationship right many many legal sets can reference the same brick and also no it's actually M and but I I broke that relationship at this one point at the reference to the brick and basically said I just referenced the brick BIID the important point here is that happens only on the Java side that's a constraint on your on the way you model your domain because basically what spring date at JDBC does is if you give it an aggregate root and says persist all this it tries to navigate the everything from the aggregate root as far as it can and considers that part of the aggregate so in the database it looks exactly as it as one would expect actually can I have the screen back if you look at the schema I don't have foreign keys in here which is basically me being lazy so it could be full with foreign keys would change a thing you actually do have the content referencing a brick here via the brick ID which could have a foreign key again to the brick so your database your database schema doesn't change at all it looks exactly the same as you would model it normally on the Java side this is modeled by on the one hand have a set of brick content items in the legal model and the brick content items then have here the brick ID and get mapped by using the table annotation to the content table you can do like find all and then provide a collection of IDs so you can carry like a hundred items in one go wouldn't be a problem oh actually to the question like the Kristin was like have a collection of 100 content items to have to get the bricks one by one first answer is you always can do will find all and then just provide a big list of ID's so you can prove load all the bricks for one legal set in one go or even for much the legal set and even beyond that this is basically or mainly this modeling thing about the crutch part of your application if you have like if you want to create a report which goes often goes across multiple aggregates there's nothing keeping you from having one big single statement joining everything together that you want and creating one big entity about out of it which then would the only thing you have to be careful about is don't try to possess that entity then funny stuff would happen but if you try to possess the row from a report that probably does strange stuff all the time everywhere okay yeah you so the question is can we do this DDD approach with JPA and the answer is definitely yes you can I mean you can do exactly the same with JPA you can just say I don't have reference to different aggregates I just put IDs in there nothing is keeping you from doing that what you also can do which is kind of a middle ground is use your Cascade annotations to basically think about what is an aggregate and then always only cascade from aggregate root to all the elements inside the aggregate but not across aggregates that is kind of easier to digest two hardcore JPA developers I guess so again you have you have multiple options okay five four minutes okay question was does this support our two DBC there's actually a separate project spring data are two DBC spring data are two DBC and spring that a JDBC have a common call where we try to reuse stuff that both models use right now they are they are like things are 2d BC can do that JDBC can't and vice versa but I guess a long term they will become more and more similar so that stuff that works in one will also work in the other well basically yes definitely spring spring five like the last the first version the first GA version came out last year which always also saw the five was it 5.1 anyway definitely beyond five and well yes we depend in in any case on the Spring Framework and sometimes on specific versions so it has to be fairly recent you can't use it with old stuff because it's a new library okay panel which one the repositories so like this one you you define repositories for the aggregate roots so in this example which you have a repository for bricks you have a repository for legal models and if you implement the rest of the diagram you would also have age groups and I think there was something else but not for every entities on a butt for every aggregate root which is actually the same thing you should do for spring data JPA on all variants for spring data but no the spring data and JDBC the question if I got it right is just like what is part of an aggregate right and what is a different aggregate and the wave spring native JDBC does that is really simple it starts as a as an aggregate at the aggregate root and tries to navigate across references and everything it finds it considers part of that aggregate if you want to delegate to a different aggregate root you have to do that by an ID which then just gets handled as a normal ID by the spring data JDBC but you know it's a different aggregate time is pretty much up if anybody else has questions so I will be for some time in front of the door and if you come up with questions later feel free to contact me on JIRA Stack Overflow Twitter or just write an email you you
Info
Channel: SpringDeveloper
Views: 37,910
Rating: 4.8116975 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: GOSW911Ox6s
Channel Id: undefined
Length: 70min 30sec (4230 seconds)
Published: Sun Oct 20 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.