[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3007?page=c...
]
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....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira