org.hibernate.HibernateException: reassociated object has dirty collection reference

There are no available Samebug tips for this exception. Do you have an idea how to solve this issue? A short tip would help users who saw this issue last week.

  • We have a Parent class with @Id of type byte[] and a Child class also with @Id of type byte[]. There is a bidirectional @OneToMany relationship "List<Child> getChildren()" in Parent with Cascade.ALL and FetchType.EAGER. We load a parent (eagerly loading its children) and detach this instance from the session. We later want to re-attach the parent + children insteances by using the Lock API with LockMode.NONE. This fails with: {panel} org.hibernate.HibernateException: reassociated object has dirty collection reference at org.hibernate.event.def.OnLockVisitor.processCollection(OnLockVisitor.java:71) at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:122) at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:83) at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:77) at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:144) at org.hibernate.event.def.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:101) at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:82) at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:774) at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:766) at org.hibernate.impl.SessionImpl.access$600(SessionImpl.java:156) at org.hibernate.impl.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2369) at com.argodata.fser.data.BlockManTest.testSimpleUpdate(BlockManTest.java:160) {panel} The problem is that {{ProxyVisitor}}'s {{isOwnerUnchanged}} uses id.equals( snapshot.getKey() ) to validate the the PersistentCollections snapshot owner id value is "equal" to the current id. For primitve keys like long and int this works, but for byte[] keys it fails as its a reference equals operation, not a value equals. If we switch our id type to long then we can re-attach the parent and children with the lock API as expected. Workaround is simple of course, just don't use array types for @Ids or wrap them with something that implements equals properly. However, considering that I believe primary arrays as keys are handled properly in other places, so I would guess that this is just an inconistency and that it should work as expected in ProxyVisitor as well. I will attach a TestCase replicating the problem shortly.
    via by Steve Ash,
  • We have a Parent class with @Id of type byte[] and a Child class also with @Id of type byte[]. There is a bidirectional @OneToMany relationship "List<Child> getChildren()" in Parent with Cascade.ALL and FetchType.EAGER. We load a parent (eagerly loading its children) and detach this instance from the session. We later want to re-attach the parent + children insteances by using the Lock API with LockMode.NONE. This fails with: {panel} org.hibernate.HibernateException: reassociated object has dirty collection reference at org.hibernate.event.def.OnLockVisitor.processCollection(OnLockVisitor.java:71) at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:122) at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:83) at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:77) at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:144) at org.hibernate.event.def.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:101) at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:82) at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:774) at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:766) at org.hibernate.impl.SessionImpl.access$600(SessionImpl.java:156) at org.hibernate.impl.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2369) at com.argodata.fser.data.BlockManTest.testSimpleUpdate(BlockManTest.java:160) {panel} The problem is that {{ProxyVisitor}}'s {{isOwnerUnchanged}} uses id.equals( snapshot.getKey() ) to validate the the PersistentCollections snapshot owner id value is "equal" to the current id. For primitve keys like long and int this works, but for byte[] keys it fails as its a reference equals operation, not a value equals. If we switch our id type to long then we can re-attach the parent and children with the lock API as expected. Workaround is simple of course, just don't use array types for @Ids or wrap them with something that implements equals properly. However, considering that I believe primary arrays as keys are handled properly in other places, so I would guess that this is just an inconistency and that it should work as expected in ProxyVisitor as well. I will attach a TestCase replicating the problem shortly.
    via by Steve Ash,
    • org.hibernate.HibernateException: reassociated object has dirty collection reference at org.hibernate.event.def.OnLockVisitor.processCollection(OnLockVisitor.java:71) at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:122) at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:83) at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:77) at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:144) at org.hibernate.event.def.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:101) at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:82) at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:774) at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:766) at org.hibernate.impl.SessionImpl.access$600(SessionImpl.java:156) at org.hibernate.impl.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2369) at com.argodata.fser.data.BlockManTest.testSimpleUpdate(BlockManTest.java:160)
    No Bugmate found.