-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: Increment aggregate root version when child entity modified
PostPosted: Sat Aug 27, 2016 11:43 am 
Newbie

Joined: Sat Aug 27, 2016 11:17 am
Posts: 12
Usually, the rationale behind clustering objects together is to form a transactionnal boundary inside which business invariants are portected. I'v noticed that with the OPTIMISTIC locking mode changes to a child entity will not cause a version increment on the root. This behavior makes it quite useless to cluster objects together in the first place.

Is there a way to configure Hibernate so that any changes to an object cluster will cause the root object's version to increment? I've read about OPTIMISTIC_FORCE_INCREMENT but I think this does increment the version regardless of if entities were changed or not. Since reads shouldn't be conflicting with other reads in most scenarios this doesn't seem so useful either.

I could always increment the version inside every mutating behaviors of the root, but that is quite error-prone. I've also though of perhaps using AOP to do this, but before looking into it I wanted to know if there was easy ways to do that. If there was a way to check if an object graph is dirty then it would make it quite easy to implement as well.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Tue Aug 30, 2016 6:11 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
What a brilliant question!

I wrote this article to demonstrate how you can implement such a behavior with Hibernate.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Tue Aug 30, 2016 10:14 am 
Newbie

Joined: Sat Aug 27, 2016 11:17 am
Posts: 12
Thanks for taking the time to provide such a great answer! However, I would have hoped for a less invasive solution that did not require bidirectionnal associations - at least not through object reference (identity reference would be better).

Hibernate must certainly have to traverse the entire object graph at some point during the persistence process, so it has to know parent-child relationships already. Would there be a way to leverage this knowledge, perhaps by relying on Hibernate internals?

I tried to inspect the source code and reverse-engineer the entire persistence process, but there are many components at play so it would be much easier for someone that already knows the inner-workings of Hibernate. I'm pretty sure there could be something interesting inside PersistenceContext and EntityEntryContext.

If the child class had an identity relationship to the parent we could perhaps rely on PersistenceContext::getEntity to find it's parent from the current session, but ideally I'd like a solution that requires no changes to the model.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Tue Aug 30, 2016 10:54 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
First of all, it must be decided whether this feature should be offered by Hibernate core.

As for unidirectional associations, you should know that they don't perform that well. If you really need a collection, a bidirectional association is a much better fit. I have a whole chapter on this topic in my book as well.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Wed Aug 31, 2016 7:57 am 
Newbie

Joined: Sat Aug 27, 2016 11:17 am
Posts: 12
Offering this as a core feature would definitely be great. I actually can't understand why it has not yet been implemented, because there is certainly a need for everyone trying to persist Aggregate Roots (http://martinfowler.com/bliki/DDD_Aggregate.html) and certainly a lot of people using Hibernate to do so.

Like Martin says, "Aggregates are the basic element of transfer of data storage - you request to load or save whole aggregates. Transactions should not cross aggregate boundaries."

As for the performance of non-bidirectional relationships in code, that is probably something that could be improved as well. Hibernate shouldn't require an explicit parent reference in the child class to be efficient. It just needs to understand the concept of an aggregated entity (an entity that has no life outside it's parent).


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Wed Aug 31, 2016 10:22 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
But it already supports the concept of aggregates through Embeddable types. In a way, it supports the whole concept if you are willing to have a single Entity and every child be mapped as an Embeddable. For multi-entity relationships, you need the workaround that I wrote about.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Wed Aug 31, 2016 1:41 pm 
Newbie

Joined: Thu May 05, 2016 4:34 pm
Posts: 2
Excellent question and excellent answer!

I've spent quite some time in the past trying to get something like this to work and I was only ever able to make it work for embeddables. Unfortunately embeddables are limited in that they can not contain collections of other entities. I posted about it on the forum but didn't receive any feedback at the time. See viewtopic.php?f=1&t=1043265. It seems this could be a nice solution for entities. I'll try it out and see if it works. :)


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Wed Aug 31, 2016 2:23 pm 
Newbie

Joined: Sat Aug 27, 2016 11:17 am
Posts: 12
"But it already supports the concept of aggregates through Embeddable types": Unfortunately, even though most does, not every aggregate consist of values only.

As for your work around, would there be a way to do it just with an identity reference rather than an object reference? Perhaps there is a way to check if another object with that id and type (or just id if a GUID) exists in the current session and retrieve it. I'd be fine having a link to the parent identity in the child entity, but having an object reference pollutes the model too much and makes reasoning about/validating the guarantees of your model much more complicated.

For instance, you may not have to unit test every child entity to make sure they aren't mutating their parent. I wouldn't do that in practice to stay pragmatic, but I think that illustrates the point.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Thu Sep 01, 2016 4:04 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
The most reasonable associations are the ones that mirror the underlying database ones. Since FK are at the core of RDBMS, @ManyToOne and @OneToOne are the most natural relationships.

For this reason, it's much more natural to use @ManyToOne and @OneToOne and occasionally bidirectional @OneToMany, then to rely on unidirectional @OneToMany and @ManyToMany. In my opinion, unidirectional associations are a code smell.

As for the identity reference topic, I have no idea what you're talking about. Feel free to find another alternative if you will.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Fri Sep 02, 2016 8:49 pm 
Newbie

Joined: Sat Aug 27, 2016 11:17 am
Posts: 12
Well, from my perspective the right associations between your objects are the ones you need to solve a business problem and protect invariants. Persistence details shouldn't bleed into nor drive the object model. Unfortunately, that is quite an utopic vision and we have to make some compromise to stay pragmatic.

"As for the identity reference topic, I have no idea what you're talking about" I just mean that if the child was holding the ID of it's parent instead of an object reference the model would be less polluted. If there would be a way of checking whether or not an object was already loaded in an Hibernate session by ID then we would use the same approach you described, but resolve the parent object using it's ID.


Top
 Profile  
 
 Post subject: Re: Increment aggregate root version when child entity modified
PostPosted: Sat Sep 03, 2016 5:42 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
Hibernate is a leaky abstraction by design. It manages to bridge the gap between OOP and RDBMS, but you still have to mind the underlying queries. Some associations are more efficient than others. Check out my Devoxx presentation for more details.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.