-->
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.  [ 5 posts ] 
Author Message
 Post subject: HibernateException: reassociated object has dirty collection
PostPosted: Mon Jun 25, 2007 12:21 pm 
Expert
Expert

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

I am using the "Conversations with detached objects" pattern. I have entities A and B such that A has a collection of Bs. The underlying tables have a foreign key from B to A, and the collection is a bag mapped as inverse="true". My code is roughly like this:

Code:
create session & transaction
select entities that will be detached
commit transaction & dispose session

(later)

create session & transaction
attach "a" of type A
create new "b" of type B
b.A = a
a.Bs.Add(b)
session.SaveOrUpdateCopy(a)
session.SaveOrUpdateCopy(b)
commit transaction & dispose session

(later)

repeat code above to add new b


When the code to create a new "b" is repeated, I get the exception "reassociated object has dirty collection" when I try to attach "a". Originally I did not update "a" since there is nothing on its underlying database row that has changed, but I added it thinking it would make NHibernate happy so it could mark the Bs collection not dirty. Unfortunately, I still get the exception.

Any idea what I'm doing wrong? BTW, A has other collections -- I'm not positive that it's even the Bs collection it's complaining about, but the exception message doesn't tell me which collection is dirty ...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 25, 2007 2:53 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
I changed my reattachment approach from ISession.Lock(entity, LockMode.None) to ISession.Update(entity) and the problem went away.

I've seen more examples in documentation that use Lock() to reattach, and only a few examples that use Update(). Come to think of it, I'm not sure why you'd ever want to use Lock() rather than Update() to reattach entities ...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 26, 2007 1:54 pm 
Regular
Regular

Joined: Wed Apr 25, 2007 4:18 am
Posts: 51
Location: Belarus, Gomel
Hi Nels_P_Olsen!

I see message somewhere in this forum about this problem - it seems that cascade=delete-orphan is the source of troubles. But IMHO it will be much more inefficient to fall back to "manual" cascading of collection operations :(
I think you may have concurency issues with .Update() approach... If your entity will be modified or even deleted between you get it in first session and "update" (attach) in second.
I bet it will be better to find out the source of this problem (it is something related to collection snapshot that NHib made to track added/removed items) and try to fix it...

_________________
WBR, Igor


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 28, 2007 9:13 pm 
Regular
Regular

Joined: Mon May 16, 2005 1:35 am
Posts: 67
You can attach an entity to a session either through Lock or Update. They have different semantics though which you need to be aware of. The Lock approach is intended to attach an object that has not been updated, so that changes can be tracked by NHibernate and then reflected in the database when the session is flushed.

Conversely, Update is indended to be applied to a disconnected entity that has already been updated. The updates are immediately reflected back to the database. Note that the entity and all cascaded entities are updated regardless of whether they have been changed. If you would like only the entities that have been updated to have UPDATE statements executed for them, you need to leverage the select-before-update option. Note that this option is inefficient because all entities eligible to be updated are first SELECTed so NHibernate can compare and determine whether an UPDATE is necessary. This option should really only be used to prevent execution of UPDATE TRIGGERs or something like that.

So in conclusion, the issue you experienced is due to using the Lock strategy to attach an entity that has already been updated. Update is the appropriate strategy for your scenario.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 03, 2007 7:25 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Since we track dirty status on our entities ourselves, it's easy for us to know if a detached entity has been modified. Still, I tried doing something like

Code:
if (entityToAttach.IsModified)
    session.Update(entityToAttach);
else
    session.Refresh(entityToAttach, LockMode.None);


However, often when it tries to do a Refresh(), I get exceptions like "cannot modify a loading collection". I don't know if the same errors occur with plain-old Lock() instead of Refresh(), but it seems that if you're going to reattach a detached entity, you should make sure it's not stale.

For the time being, we're always doing Update(), and if an exception gets thrown, do a Get() and then manually, painstakingly merge in any dirty properties on the entity originally requested for reattachment, return the one from the session and expect the caller to deal with the fact that the instance "attached" is not the one passed ...


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