renatoaraujoc
renatoaraujoc

Reputation: 357

Real world usage for CascadeTypes (DEATCH/REMOVE/REFRESH) on OneToMany?

I am having a real hard time trying to find out a real world usage for CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH in a OneToMany relationship.

Let's put it on an example:

User hasMany UserAccess 

Everytime the User logs in a Website, it is created a UserAccess object containing his IP Adress and DateTime.

  1. How could those 03 CascadeTypes above affect this association in a real world procedure? I can pretty much see the usage on CascadeType.PERSIST (for cascading persist) and CascadeType.REMOVE (to remove the child if User is deleted). OrphanRemoval is also derisable in this case, no doubts.

  2. If my example is not complete enough, could anyone formulate a real world example on this subject?

Thank you!

Upvotes: 2

Views: 1743

Answers (1)

Pace
Pace

Reputation: 43887

I'm having a hard time thinking with your example only because detach and merge tend to be for entities that will be accessed outside of your sphere of influence. For that reason, I'll stick with some boring example like a document collection.

Two points before I get into the example:

First, a useful rule of thumb for understanding Hibernate cascades is to think of them in this way: "If I cascade operation X from A to B then when I call operation X on A Hibernate will automatically call operation X on all of the associated B's. (orphan removal is an exception)"

Second, with that in mind, the advantage of all cascades other than orphan removal is just to save you the hassle of iterating through the child objects and calling the operation on the child objects. There is no functional difference between you doing it yourself and letting Hibernate do it.

Now, for the example:

Assume your application keeps track of a DocumentCollection object which has many Document objects which have many Paragraph objects. You want this application to be used by a desktop interface built by some other team. Your team owns the back-end, the other team owns the front-end, but rather than a web application, all of this is happening within the same process.

To keep matters simple, the interface will grab a DocumentCollection wholesale so your public API will simply be:

public DocumentCollection fetchCollection(String collectionName);
public void updateCollection(DocumentCollection collection);

Now, because you have no idea what the interface team is going to do with your DocumentCollection after they fetch it then the last thing you would want to do is pass a live, persistent entity back to them, the transaction management alone would be terrible. To resolve this you want to detach anything before you send it on.

Now typically you wouldn't really need to detach anything because you would close your session before you returned the object anyways so lets complicate things even further. Lets pretend your user is interacting with some multi-page form widget and you want to keep a session open for the duration of the widget (this is session-per-conversation but honestly if you think about the example for too long it becomes contrived but this is the best I can do off the top of my head).

All of this is really justifying why you would want to detach something in the first place, which I suspect is more at the heart of your question than you may think. So, given this contrived scenario your choices are:

  1. Call detach on the DocumentCollection, iterate through each Document and call detach on that, then iterate through each Paragraph and call detach on those.
  2. Cascade detach on the DocumentCollection->Document and Document->Paragraph relationships and just call detach on the DocumentCollection, letting Hibernate do the iteration for you.

Of course, once the user has finished modifying the document and passes it back in to save it, then you will have to call merge on everything and so cascading merge will be very useful.

For refresh, lets look at a different example (this one may be even more contrived as I have not done this myself). Let's assume that you decide you do trust your interface team and you don't want to detach the objects. This allows you to skip the calls to detach and merge. Now, lets assume the user hits some kind of "revert to last save" button. You decide to implement this by "refreshing" the DocumentCollection and everything underneath. Here, a cascade would be very helpful as it would save you a bunch of iteration.

Upvotes: 4

Related Questions