From 77a75a94b50d80d4a6e41c279448fc768d94b9ca Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Tue, 20 Jul 2010 01:22:12 +0000 Subject: [PATCH] HHH-2269 : Many-to-one cascade fails with TransientObjectException if inverse collection is CascadeType.DELETE_ORPHAN git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19969 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../AbstractPersistentCollection.java | 22 ++++++++++++++----- .../BidirectionalOneToManyCascadeTest.java | 4 +--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/hibernate/collection/AbstractPersistentCollection.java b/core/src/main/java/org/hibernate/collection/AbstractPersistentCollection.java index 343f1fbdc8..fd55345b08 100644 --- a/core/src/main/java/org/hibernate/collection/AbstractPersistentCollection.java +++ b/core/src/main/java/org/hibernate/collection/AbstractPersistentCollection.java @@ -36,14 +36,17 @@ import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; import org.hibernate.LazyInitializationException; import org.hibernate.engine.CollectionEntry; +import org.hibernate.engine.EntityEntry; import org.hibernate.engine.ForeignKeys; import org.hibernate.engine.SessionImplementor; +import org.hibernate.engine.Status; import org.hibernate.engine.TypedValue; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.pretty.MessageHelper; import org.hibernate.type.Type; import org.hibernate.util.CollectionHelper; import org.hibernate.util.EmptyIterator; +import org.hibernate.util.IdentitySet; import org.hibernate.util.MarkerObject; /** @@ -905,20 +908,29 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access java.util.Set currentIds = new HashSet(); + java.util.Set currentSaving = new IdentitySet(); for ( Iterator it=currentElements.iterator(); it.hasNext(); ) { Object current = it.next(); if ( current!=null && ForeignKeys.isNotTransient(entityName, current, null, session) ) { - Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, current, session); - currentIds.add( new TypedValue( idType, currentId, session.getEntityMode() ) ); + EntityEntry ee = session.getPersistenceContext().getEntry( current ); + if ( ee != null && ee.getStatus() == Status.SAVING ) { + currentSaving.add( current ); + } + else { + Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, current, session); + currentIds.add( new TypedValue( idType, currentId, session.getEntityMode() ) ); + } } } // iterate over the *old* list for ( Iterator it=oldElements.iterator(); it.hasNext(); ) { Object old = it.next(); - Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, old, session); - if ( !currentIds.contains( new TypedValue( idType, oldId, session.getEntityMode() ) ) ) { - res.add(old); + if ( ! currentSaving.contains( old ) ) { + Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, old, session); + if ( !currentIds.contains( new TypedValue( idType, oldId, session.getEntityMode() ) ) ) { + res.add(old); + } } } diff --git a/testsuite/src/test/java/org/hibernate/test/cascade/BidirectionalOneToManyCascadeTest.java b/testsuite/src/test/java/org/hibernate/test/cascade/BidirectionalOneToManyCascadeTest.java index 93ae4330f3..1d72e5e281 100644 --- a/testsuite/src/test/java/org/hibernate/test/cascade/BidirectionalOneToManyCascadeTest.java +++ b/testsuite/src/test/java/org/hibernate/test/cascade/BidirectionalOneToManyCascadeTest.java @@ -118,10 +118,8 @@ public class BidirectionalOneToManyCascadeTest extends FunctionalTestCase { * Saves the child object with the parent when the one-to-many association * uses cascade="all-delete-orphan" and the many-to-one association uses * cascade="all" - *

- * This test is known to fail. See HHH-2269. */ - public void testSaveOrphanDeleteChildWithParentFailureExpected() { + public void testSaveOrphanDeleteChildWithParent() { Session session = openSession(); Transaction txn = session.beginTransaction(); Parent parent = new Parent();