[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-3007) Unchanged persistent set gets marked dirty on session.merge()

Johan Andrén (JIRA) noreply at atlassian.com
Fri Dec 10 07:11:13 EST 2010


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-3007?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=39334#action_39334 ] 

Johan Andrén commented on HHH-3007:
-----------------------------------

We seem to be having this problem on 3.2.4.SP1 (shipped with JBoss 4.2.2) triggered by a merge() on an entity two relations away.
So em.merge(a)
{{A.b}} ({{List<B>}} annotated with {{CascadeType.PERSIST}} and {{CascadeType.MERGE}})
{{B.c}} ({{Set<C>}} annotated with {{CascadeType.ALL}} and {{CascadeType.DELETE_ORPHAN}})

causes our JPA-entity listener on {{B}} get a callback saying that {{B}} is changed even though it is not. The reason beeing the {{CollectionType.replace}} mentioned by Lars.


Call stack:
{noformat}
AbstractPersistentCollection.dirty:70
PersistentSet.clear:302
CollectionType.replaceElements:445
CollectionType.replace:524
TypeFactory.replace:482
DefaultMergeEventListener.copyValues:340
DefaultMergeEventListener.entityIsPersistent:153
DefaultMergeEventListener.onMerge:126
SessionImpl.fireMerge:687
SessionImpl.merge:669
CascadingAction$6.cascade:245
Cascade.cascadeToOne:268
Cascade.cascadeAssociation:216
Cascade.cascadeProperty:169
Cascade.cascadeCollectionElements:296
Cascade.cascadeCollection:242	
Cascade.cascadeAssociation:219
Cascade.cascadeProperty:169
Cascade.cascade:130
DefaultMergeEventListener.cascadeOnMerge:407
DefaultMergeEventListener.entityIsPersistent:152
DefaultMergeEventListener.onMerge:126	
DefaultMergeEventListener.onMerge:53
{noformat}


I'll try to create a repeatable testcase.

> Unchanged persistent set gets marked dirty on session.merge()
> -------------------------------------------------------------
>
>                 Key: HHH-3007
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3007
>             Project: Hibernate Core
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.2.5
>            Reporter: Lars Koedderitzsch
>
> Persistent sets are marked dirty on session.merge() even if there have been no changes to the collection.
> This is especially painful when the collection is immutable and results in an "changed an immutable collection instance" exception on flush.
> I tracked the behaviour down a bit and believe the problem to be in CollectionType.replace().
> Here the passed in orginal PersistentSet is replaced by a plain HashSet in this line: 
> Object result = target == null || target == original ? instantiateResult( original ) : target;
> The "result" object (HashSet) is then passed to the CollectionType.replaceElements() method (instead of the original PersistentSet).
> In CollectionType.replaceElements() the code to clear the dirty state of the collection does not execute anymore, because the passed-in "original" collection is the described HashSet and *not* the original PersistentSet.
> This way the PersistentSet remains marked dirty.
> A workaround is to manually clear the dirty state of an immutable collection after merge but before flush.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

       



More information about the hibernate-issues mailing list