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.  [ 8 posts ] 
Author Message
 Post subject: ObjectDeletedException problem
PostPosted: Mon Sep 17, 2007 12:51 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Hibernate version: 1.2.0.GA

We have several cases in our object model where three classes set up such that one "child" class appears to have two "parent" classes from the mapping. I.e. although only one is the "true" parent, the "false" parent still keeps a collection of the "children". Collection properties on both parents are set up as cascade="all-delete-orphan".

When I try to delete a "true" parent, I get ObjectDeletedException because the child is still referenced by the "false" parent. This is not an isolated case; I'm sure we have many others like this in our data model.

It may not be possible for us to have the code that attempts to delete the "true" parent get cluttered with worrying about all other possible references other objects may have to its cascade-delete children, so it is not practical or desirable for the code requesting the delete to find and remove all these extraneous child references first.

Is it possible to know when NHibernate is attempting to delete an entity, and still make data modifications, so that we can code each entity to remove itself from those referencing it when it's getting deleted? At least that would put the responsibility for the dissociations with the classes causing the trouble, and relieve the caller trying to delete the root object from having to know about all the possible connections of the cascade-deleted children.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 17, 2007 10:01 pm 
Regular
Regular

Joined: Fri Jan 20, 2006 7:45 pm
Posts: 97
Location: San Antonio, TX
Can you model this for us and give us a better picture of class structure and mapping? I'm confused by "false parent" for one. Should a false parent be able to cascade delete? It sounds a bit circular. If nothing else you have a nasty custody batle on your hands.

Shouldn't cascade="all-delete-orphan" be on the child, as well as inverse="true"? In this case, if I remove a child from a collection on the parent, it's deleted from the repository. Still unsure what would happen with 2 parents (would have to test).

So, in a nutshell:

If I put inverse="true" on a child, adding the child to a collection on the parent would create a new one by saving the child after associating the two...
Code:
Parent parent = parentDao.Get(parentId);
Chile child = new Child(); //child has prentId in database

child.Parent = parent;
parent.Children.Add(child);
session.Save(child);
session.Flush(); //A child is born! (using one insert)


Now if I add inverse="true" and cascade="all" to the Parent's collection of Children we wouldn't need the explicit save:
Code:
Parent parent = parentDao.Get(parentId);
Chile child = new Child(); //child has prentId in database

child.Parent = parent;
parent.Children.Add(child);
session.Flush(); //A child is born!

Given this, if I delete the parent, all the children get deleted with it. But, if I remove a child from the parent.Children collection, the association is severed and the child is orphaned and still in the database without the association to the parent (if a not null constraint wasn't violated first).

If a child can't exist without a parent, then we use cascade="all-delete-orphan" on the child so that if the child is removed from parent.Children then it is deleted from the database (because we euthanise all orphans).

Make sense?

_________________
Dum spiro, spero
-------------------------------
Rate my post if it helps...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 10:13 am 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Here is a more concrete (but still contrived) example:

"True parent" Contact has an inverse bag of ContactPhones. The cascade is set up as all-delete-orphan. The ContactPhone has a reference to another entity called PhoneType. Now, the problem appears if PhoneType actually has an inverse bag to ContactPhones (which holds all phones with its phone type). The PhoneType keeping its own inverse collection is what I'm calling a "false parent". I actually have a few cases that are set up like this (not between PhoneType and ContactPhone though, I just made that up because the objects are easy to understand).

If I try to delete a Contact, the cascade to its ContactPhones fails because they are still referenced in the PhoneType's collections. There's no way the code requesting to delete a Contact should have to know that there is this distant inverse relationship between PhoneType and ContactPhone, and somehow attempt to dissociate these references before doing its delete.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 10:21 am 
Regular
Regular

Joined: Fri Jan 20, 2006 7:45 pm
Posts: 97
Location: San Antonio, TX
So, in the example, is ContactPhone basically an association table between Contact and PhoneType, or is there more to ContactPhone?

_________________
Dum spiro, spero
-------------------------------
Rate my post if it helps...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 1:51 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
The ContactPhone in this example has its own data in addition to PhoneType. Its reference to PhoneType (from its perspective at least) is no different than any other non-parent entity reference.

So, my issue is that sometimes you want to have these independent, referenced classes like PhoneType have inverse collections back to the things that reference them. This interferes with cascade deletes elsewhere.

This issue doesn't even touch on whether the PhoneType's collection of ContactPhones should cascade delete; in the cases I've tried setting up something like this, the class analogous to PhoneType is not something you would ever delete. At most you would add a a boolean Active/Inactive property so that new data can't reference it ...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 2:42 pm 
Expert
Expert

Joined: Fri May 13, 2005 11:13 am
Posts: 292
Location: Rochester, NY
Nels, looking through the source, that exception is thrown in a few circumstances. On a delete you are probably getting the message: "deleted object would be re-saved by cascade (remove deleted object from associations)" (from SessionImpl.ForceFlush)

This doesn't seem like a bug so much as a logical blocking issue because of the cascades. It would be nice if NH took care of those removals for us, but this might be a case where it isn't feasible for it to be that "smart".

Also, it would appear that you don't have to abandon the "secondary/false/adopted parent" relationship entirely, but only the cascades on those. This seems reasonable. I know these are "dumbed-down" examples you've provided--is it reasonable in your real scenarios?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 5:56 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Actually, cascade is already set to "none" for the "false parent"s collection of "children". It's the "true parent"s collection of children that has cascade set to "all-delete-orphan", and that cascade needs to stay.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 02, 2008 5:39 am 
Newbie

Joined: Tue Sep 02, 2008 5:35 am
Posts: 1
I'm experiencing the same problem.
A child that exists in two parent collections and we want it removed when any of the parents get deleted.

Any suggestions ?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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.