title: Hibernate 3.6.6.Final (JBoss 6.1) merge() transient object tree
body: <p>I try to save an object tree with Hibernate's merge() method. Entity <code>Auftrag</code> (means "order" in English) contains a collection of <code>Auftragsposition</code> objects, mapped with <code>cascade="all-delete-orphan</code>. </p>
  
  <p>The persisting occurs in a stateless session bean, called via RMI. The method opens a new (clean) <code>Session</code> instance. When an already existing order is saved, merge() tries to load the entity from the DB and in turn associates the just loaded dependent order positions with the session's persistence context. Later on, when the merge() operation is cascaded upon the order positions, a NonUniqueObjectException occurs (because the transient order position differs from the Hibernate-loaded one).</p>
  
  <p>saveOrUpdate() yields similar results.</p>
  
  <p>Does an intelligent (one or as few as possible lines-of-code) solution exist? Or does one have to work around that behaviour, e.g. by recursing over the object tree and saving (as in associate with the session) the transient objects first?</p>
  
  <p>(P.S.: I get that exception now because I threw an old, custom made subclass named <code>AuftragEntityPersister</code> away - which purged the whole object tree from the database and then inserted the stuff again, probably to work around that very problem.)</p>
  
  <p>Cf. the exception stacktrace:</p>
  
  <pre><code>13:54:16,052 ERROR [de.redacted.services.persistence.auftrag.AuftragPersistenceSessionBean] Rolling back due to Hibernate-Exception: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [de.redacted.domain.auftrag.Auftragsposition#de.redacted.domain.angebot.AngebotsPositionPK@b4000000]
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:190) [:3.6.6.Final]
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:143) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:415) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:341) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:303) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:258) [:3.6.6.Final]
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:877) [:3.6.6.Final]
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:859) [:3.6.6.Final]
    at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:279) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204) [:3.6.6.Final]
    at org.hibernate.engine.Cascade.cascade(Cascade.java:161) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:630) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:490) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:255) [:3.6.6.Final]
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) [:3.6.6.Final]
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:867) [:3.6.6.Final]
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:851) [:3.6.6.Final]
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:855) [:3.6.6.Final]
    at de.redacted.services.persistence.auftrag.AuftragPersistenceSessionBean.saveAuftrag(AuftragPersistenceSessionBean.java:1145) [:]
    at de.redacted.services.persistence.auftrag.AuftragPersistenceSessionBean.saveAuftrag(AuftragPersistenceSessionBean.java:873) [:]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_21]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_21]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_21]
    at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_21]
    at org.jboss.invocation.Invocation.performCall(Invocation.java:386) [:6.1.0.Final]
    at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:233) [:6.1.0.Final]
    at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:156) [:6.1.0.Final]
    at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:173) [:6.1.0.Final]
    at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:63) [:6.1.0.Final]
    at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:121) [:6.1.0.Final]
    at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:350) [:6.1.0.Final]
    at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:181) [:6.1.0.Final]
    at org.jboss.ejb.plugins.SecurityInterceptor.process(SecurityInterceptor.java:228) [:6.1.0.Final]
    at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:211) [:6.1.0.Final]
    at org.jboss.ejb.plugins.security.PreSecurityInterceptor.process(PreSecurityInterceptor.java:100) [:6.1.0.Final]
    at org.jboss.ejb.plugins.security.PreSecurityInterceptor.invoke(PreSecurityInterceptor.java:84) [:6.1.0.Final]
    at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:205) [:6.1.0.Final]
    at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:138) [:6.1.0.Final]
    at org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:650) [:6.1.0.Final]
    at org.jboss.ejb.Container.invoke(Container.java:1072) [:6.1.0.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_21]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_21]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_21]
    at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_21]
    at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:157) [:6.0.0.GA]
    at org.jboss.mx.server.Invocation.dispatch(Invocation.java:96) [:6.0.0.GA]
    at org.jboss.mx.server.Invocation.invoke(Invocation.java:88) [:6.0.0.GA]
    at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:271) [:6.0.0.GA]
    at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:670) [:6.0.0.GA]
    at org.jboss.invocation.unified.server.UnifiedInvoker.invoke(UnifiedInvoker.java:232) [:6.1.0.Final]
    at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:967) [:6.1.0.Final]
    at org.jboss.remoting.transport.socket.ServerThread.completeInvocation(ServerThread.java:791) [:6.1.0.Final]
    at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:744) [:6.1.0.Final]
    at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:586) [:6.1.0.Final]
    at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:234) [:6.1.0.Final]
  </code></pre>