[hibernate-commits] Hibernate SVN: r18957 - in core/trunk/testsuite/src/test/java/org/hibernate/test: immutable/entitywithmutablecollection and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Mar 10 06:03:10 EST 2010


Author: gbadner
Date: 2010-03-10 06:03:08 -0500 (Wed, 10 Mar 2010)
New Revision: 18957

Added:
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithOneToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Contract.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/ContractVariation.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Info.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Owner.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Party.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Plan.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationOneToManyJoin.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersionedOneToManyJoin.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseManyToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyJoinTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseManyToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyFailureExpectedTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinFailureExpectedTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariation.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationOneToManyJoin.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationUnidir.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersioned.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersionedOneToManyJoin.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyUnidirTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyJoinTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyUnidirTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseManyToManyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyJoinTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyTest.java
Modified:
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
Log:
HHH-4993 : Updates to read-only entity associations made while in persistent state are ignored by flush (tests only)

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -11,6 +11,7 @@
 public class Contract implements Serializable {
 	
 	private long id;
+	private long version;
 	private String customerName;
 	private String type;
 	private List variations;
@@ -26,8 +27,8 @@
 
 	public Contract(Plan plan, String customerName, String type) {
 		plans = new HashSet();
-		plans.add( plan );
 		if ( plan != null ) {
+			plans.add( plan );
 			plan.getContracts().add( this );
 		}
 		this.customerName = customerName;
@@ -38,6 +39,14 @@
 		infos = new HashSet();
 	}
 
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+	
 	public Set getPlans() {
 		return plans;
 	}

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -37,7 +37,7 @@
             <generator class="increment"/>
         </id>
         <!-- <many-to-one name="contract" update="false" insert="false"/> -->
-        <many-to-one name="contract" not-null="true"/>
+        <many-to-one name="contract" not-null="false"/>
         <property name="name" not-null="true"/>
         <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
             <key column="party"/>
@@ -85,7 +85,7 @@
 		<property name="text" type="text"/>
         <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
             <key>
-                <column name="contract"/>
+                <column name="contractvariation"/>
                 <column name="version"/>
             </key>
             <one-to-many class="Info"/>

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -1222,6 +1222,234 @@
 		assertDeleteCount( 4 );
 	}
 
+	public void testImmutableEntityAddImmutableToInverseMutableCollection() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gavin", "phone");
+		ContractVariation cv1 = new ContractVariation(1, c);
+		cv1.setText("expensive");
+		ContractVariation cv2 = new ContractVariation(2, c);
+		cv2.setText("more expensive");
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		Party party = new Party( "a party" );
+		s.persist( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 4 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c.addParty( new Party( "a new party" ) );
+		s.update( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c.addParty( party );
+		s.update( c );
+		t.commit();
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertEquals( c.getCustomerName(), "gavin" );
+		assertEquals( c.getVariations().size(), 2 );
+		Iterator it = c.getVariations().iterator();
+		cv1 = (ContractVariation) it.next();
+		assertEquals( cv1.getText(), "expensive" );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		//assertEquals( 2, c.getParties().size() );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 4 );
+	}
+	
+	public void testImmutableEntityRemoveImmutableFromInverseMutableCollection() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gavin", "phone");
+		ContractVariation cv1 = new ContractVariation(1, c);
+		cv1.setText("expensive");
+		ContractVariation cv2 = new ContractVariation(2, c);
+		cv2.setText("more expensive");
+		Party party = new Party( "party1" );
+		c.addParty( party );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 4 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		party = ( Party ) c.getParties().iterator().next();
+		c.removeParty( party );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertEquals( c.getCustomerName(), "gavin" );
+		assertEquals( c.getVariations().size(), 2 );
+		Iterator it = c.getVariations().iterator();
+		cv1 = (ContractVariation) it.next();
+		assertEquals( cv1.getText(), "expensive" );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		//assertEquals( 0, c.getParties().size() );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 4 );
+	}
+
+	public void testImmutableEntityRemoveImmutableFromInverseMutableCollectionByDelete() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gavin", "phone");
+		ContractVariation cv1 = new ContractVariation(1, c);
+		cv1.setText("expensive");
+		ContractVariation cv2 = new ContractVariation(2, c);
+		cv2.setText("more expensive");
+		Party party = new Party( "party1" );
+		c.addParty( party );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 4 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		party = ( Party ) c.getParties().iterator().next();
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.delete( party );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertEquals( c.getCustomerName(), "gavin" );
+		assertEquals( c.getVariations().size(), 2 );
+		Iterator it = c.getVariations().iterator();
+		cv1 = (ContractVariation) it.next();
+		assertEquals( cv1.getText(), "expensive" );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		assertEquals( 0, c.getParties().size() );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testImmutableEntityRemoveImmutableFromInverseMutableCollectionByDeref() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gavin", "phone");
+		ContractVariation cv1 = new ContractVariation(1, c);
+		cv1.setText("expensive");
+		ContractVariation cv2 = new ContractVariation(2, c);
+		cv2.setText("more expensive");
+		Party party = new Party( "party1" );
+		c.addParty( party );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 4 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		party = ( Party ) c.getParties().iterator().next();
+		party.setContract( null );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( party );
+		t.commit();
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		party = ( Party ) s.get( Party.class, party.getId() );
+		assertNotNull( party.getContract() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertEquals( c.getCustomerName(), "gavin" );
+		assertEquals( c.getVariations().size(), 2 );
+		Iterator it = c.getVariations().iterator();
+		cv1 = (ContractVariation) it.next();
+		assertEquals( cv1.getText(), "expensive" );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		assertEquals( 1, c.getParties().size() );
+	    party = ( Party ) c.getParties().iterator().next();
+		assertEquals( "party1", party.getName() );
+		assertSame( c, party.getContract() );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 4 );
+	}
+
 	protected void clearCounts() {
 		getSessions().getStatistics().clear();
 	}

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -7,6 +7,7 @@
 
 	private long id;
 	private String text;
+	private long version;
 
 	public Info() {
 		super();
@@ -16,6 +17,14 @@
 		this.text = text;
 	}
 
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+
 	public String getText() {
 		return text;
 	}

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -10,6 +10,7 @@
 public class Party implements Serializable {
 
 	private long id;
+	private long version;
 	private Contract contract;
 	private String name;
 	private Set infos = new HashSet();
@@ -22,6 +23,14 @@
 		this.name = name;
 	}
 
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+	
 	public String getName() {
 		return name;
 	}

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -9,6 +9,7 @@
 public class Plan implements Serializable {
 
 	private long id;
+	private long version;
 	private String description;
 	private Set contracts;
 	private Set infos;
@@ -23,6 +24,14 @@
 		infos = new HashSet();
 	}
 
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+
 	public long getId() {
 		return id;
 	}

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithManyToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,1103 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.util.Iterator;
+
+import org.hibernate.MappingException;
+import org.hibernate.Session;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.junit.functional.FunctionalTestCase;
+
+/**
+ * @author Gail Badner
+ */
+public abstract class AbstractEntityWithManyToManyTest extends FunctionalTestCase {
+	private boolean isPlanContractsInverse;
+	private boolean isPlanContractsBidirectional;
+	private boolean isPlanVersioned;
+	private boolean isContractVersioned;
+
+	public AbstractEntityWithManyToManyTest(String str) {
+		super(str);
+	}
+
+	public void configure(Configuration cfg) {
+		cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
+		cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
+	}
+
+	public abstract String[] getMappings();
+
+	protected void prepareTest() throws Exception {
+		super.prepareTest();
+		isPlanContractsInverse = ( ( SessionFactoryImpl ) getSessions() ).getCollectionPersister( Plan.class.getName() + ".contracts" ).isInverse();
+		try {
+			 ( ( SessionFactoryImpl ) getSessions() ).getCollectionPersister( Contract.class.getName() + ".plans" );
+			isPlanContractsBidirectional = true;
+		}
+		catch ( MappingException ex) {
+			isPlanContractsBidirectional = false;	
+		}
+		isPlanVersioned = ( ( SessionFactoryImpl ) getSessions() ).getEntityPersister( Plan.class.getName() ).isVersioned();
+		isContractVersioned = ( ( SessionFactoryImpl ) getSessions() ).getEntityPersister( Contract.class.getName() ).isVersioned();
+	}
+
+	public void testUpdateProperty() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		p.addContract( new Contract( null, "gail", "phone") );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(p);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = (Plan) s.createCriteria( Plan.class ).uniqueResult();
+		p.setDescription( "new plan" );
+		assertEquals( 1, p.getContracts().size() );
+		Contract c = ( Contract ) p.getContracts().iterator().next();
+		c.setCustomerName( "yogi" );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = (Plan) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 1, c.getPlans().size() );
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyManyToManyCollectionOfNew() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		p.addContract( new Contract( null, "gail", "phone") );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(p);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		Contract c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 1, c.getPlans().size() );
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete(p);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyManyToManyCollectionOfExisting() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		p.addContract( c );
+		s = openSession();
+		t = s.beginTransaction();
+		s.save(p);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 1, c.getPlans().size() );
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete(p);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testAddNewManyToManyElementToPersistentEntity() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.get( Plan.class, p.getId() );
+		assertEquals( 0, p.getContracts().size() );
+		p.addContract( new Contract( null, "gail", "phone") );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		Contract c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 1, c.getPlans().size() );
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testAddExistingManyToManyElementToPersistentEntity() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.get( Plan.class, p.getId() );
+		assertEquals( 0, p.getContracts().size() );
+		c = ( Contract ) s.get( Contract.class, c.getId() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+		p.addContract( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithEmptyManyToManyCollectionUpdateWithExistingElement() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.addContract( c );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyManyToManyCollectionUpdateWithNewElement() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(p);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		Contract newC = new Contract( null, "sherman", "telepathy" );
+		p.addContract( newC );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 2, p.getContracts().size() );
+		for ( Iterator it=p.getContracts().iterator(); it.hasNext(); ) {
+			Contract aContract = ( Contract ) it.next();
+			if ( aContract.getId() == c.getId() ) {
+				assertEquals( "gail", aContract.getCustomerName() );
+			}
+			else if ( aContract.getId() == newC.getId() ) {
+				assertEquals( "sherman", aContract.getCustomerName() );
+			}
+			else {
+				fail( "unknown contract" );
+			}
+			if ( isPlanContractsBidirectional ) {
+				assertSame( p, aContract.getPlans().iterator().next() );
+			}
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testCreateWithEmptyManyToManyCollectionMergeWithExistingElement() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.addContract( c );
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.merge( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyManyToManyCollectionMergeWithNewElement() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		Contract newC = new Contract( null, "yogi", "mail" );
+		p.addContract( newC );
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.merge( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 2, p.getContracts().size() );
+		for ( Iterator it=p.getContracts().iterator(); it.hasNext(); ) {
+			Contract aContract = ( Contract ) it.next();
+			if ( aContract.getId() == c.getId() ) {
+				assertEquals( "gail", aContract.getCustomerName() );
+			}
+			else if ( ! aContract.getCustomerName().equals( newC.getCustomerName() ) ) {
+				fail( "unknown contract:" + aContract.getCustomerName() );
+			}
+			if ( isPlanContractsBidirectional ) {
+				assertSame( p, aContract.getPlans().iterator().next() );
+			}
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testRemoveManyToManyElementUsingUpdate() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.removeContract( c );
+		assertEquals( 0, p.getContracts().size() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( p );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		if ( isPlanContractsInverse ) {
+			assertEquals( 1, p.getContracts().size() );
+			c = ( Contract ) p.getContracts().iterator().next();
+			assertEquals( "gail", c.getCustomerName() );
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		else {
+			assertEquals( 0, p.getContracts().size() );
+			c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+			if ( isPlanContractsBidirectional ) {
+				assertEquals( 0, c.getPlans().size() );
+			}
+			s.delete( c );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testRemoveManyToManyElementUsingUpdateBothSides() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.removeContract( c );
+		assertEquals( 0, p.getContracts().size() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( p );
+		s.update( c );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned && isPlanVersioned ? 2 : 0 );
+		assertDeleteCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 0, p.getContracts().size() );
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+		s.delete( c );
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testRemoveManyToManyElementUsingMerge() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.removeContract( c );
+		assertEquals( 0, p.getContracts().size() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.merge( p );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		if ( isPlanContractsInverse ) {
+			assertEquals( 1, p.getContracts().size() );
+			c = ( Contract ) p.getContracts().iterator().next();
+			assertEquals( "gail", c.getCustomerName() );
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		else {
+			assertEquals( 0, p.getContracts().size() );
+			c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+			if ( isPlanContractsBidirectional ) {
+				assertEquals( 0, c.getPlans().size() );
+			}
+			s.delete( c );
+		}
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testRemoveManyToManyElementUsingMergeBothSides() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.removeContract( c );
+		assertEquals( 0, p.getContracts().size() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.merge( p );
+		c = ( Contract ) s.merge( c );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned  && isPlanVersioned ? 2 : 0 );
+		assertDeleteCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 0, p.getContracts().size() );
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+		s.delete( c );
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testDeleteManyToManyElement() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( p );
+		p.removeContract( c );
+		s.delete( c );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 0, p.getContracts().size() );
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		assertNull( c );
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testRemoveManyToManyElementByDelete() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		Contract c = new Contract( null, "gail", "phone");
+		p.addContract( c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		p.removeContract( c );
+		assertEquals( 0, p.getContracts().size() );
+		if ( isPlanContractsBidirectional ) {
+			assertEquals( 0, c.getPlans().size() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( p );
+		s.delete( c );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isPlanVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 0, p.getContracts().size() );
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testManyToManyCollectionOptimisticLockingWithMerge() {
+		clearCounts();
+
+		Plan pOrig = new Plan( "plan" );
+		Contract cOrig = new Contract( null, "gail", "phone");
+		pOrig.addContract( cOrig );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( pOrig );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		Plan p = ( Plan ) s.get( Plan.class, pOrig.getId() );
+		Contract newC = new Contract( null, "sherman", "note" );
+		p.addContract( newC );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		pOrig.removeContract( cOrig );
+		try {
+			s.merge( pOrig );
+			assertFalse( isContractVersioned );
+		}
+		catch (StaleObjectStateException ex) {
+			assertTrue( isContractVersioned);
+		}
+		finally {
+			t.rollback();
+		}
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		s.delete( p );
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testManyToManyCollectionOptimisticLockingWithUpdate() {
+		clearCounts();
+
+		Plan pOrig = new Plan( "plan" );
+		Contract cOrig = new Contract( null, "gail", "phone");
+		pOrig.addContract( cOrig );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(pOrig);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		Plan p = ( Plan ) s.get( Plan.class, pOrig.getId() );
+		Contract newC = new Contract( null, "yogi", "pawprint" );
+		p.addContract( newC );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		pOrig.removeContract( cOrig );
+		s.update( pOrig );
+		try {
+			t.commit();
+			assertFalse( isContractVersioned );
+		}
+		catch (StaleObjectStateException ex) {
+			assertTrue( isContractVersioned);
+			t.rollback();
+		}
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = ( Plan ) s.createCriteria( Plan.class ).uniqueResult();
+		s.delete( p );
+		s.createQuery( "delete from Contract" ).executeUpdate();
+		assertEquals( new Long( 0 ), s.createCriteria(Plan.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+	}
+
+	public void testMoveManyToManyElementToNewEntityCollection() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		p.addContract( new Contract( null, "gail", "phone" ) );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = (Plan) s.createCriteria( Plan.class ).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		Contract c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		p.removeContract( c );
+		Plan p2 = new Plan( "new plan" );
+		p2.addContract( c );
+		s.save( p2 );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isPlanVersioned && isContractVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p.getId() ) )).uniqueResult();
+		p2 = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p2.getId() ) )).uniqueResult();
+		/*
+		if ( isPlanContractsInverse ) {
+			assertEquals( 1, p.getContracts().size() );
+			c = ( Contract ) p.getContracts().iterator().next();
+			assertEquals( "gail", c.getCustomerName() );
+			if ( isPlanContractsBidirectional ) {
+				assertSame( p, c.getPlans().iterator().next() );
+			}
+			assertEquals( 0, p2.getContracts().size() );
+		}
+		else {
+		*/
+			assertEquals( 0, p.getContracts().size() );
+			assertEquals( 1, p2.getContracts().size() );
+			c = ( Contract ) p2.getContracts().iterator().next();
+			assertEquals( "gail", c.getCustomerName() );
+			if ( isPlanContractsBidirectional ) {
+				assertSame( p2, c.getPlans().iterator().next() );
+			}
+		//}
+		s.delete( p );
+		s.delete( p2 );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testMoveManyToManyElementToExistingEntityCollection() {
+		clearCounts();
+
+		Plan p = new Plan( "plan" );
+		p.addContract( new Contract( null, "gail", "phone" ) );
+		Plan p2 = new Plan( "plan2" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( p );
+		s.persist( p2 );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 3 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p.getId() ) )).uniqueResult();
+		assertEquals( 1, p.getContracts().size() );
+		Contract c = ( Contract ) p.getContracts().iterator().next();
+		assertEquals( "gail", c.getCustomerName() );
+		if ( isPlanContractsBidirectional ) {
+			assertSame( p, c.getPlans().iterator().next() );
+		}
+		p.removeContract( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( isPlanVersioned && isContractVersioned ? 2 : 0 );
+		clearCounts();
+		
+		s = openSession();
+		t = s.beginTransaction();
+		p2 = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p2.getId() ) )).uniqueResult();
+		c = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c.getId() ) )).uniqueResult();
+		p2.addContract( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( isPlanVersioned && isContractVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		p = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p.getId() ) )).uniqueResult();
+		p2 = (Plan) s.createCriteria( Plan.class ).add( Restrictions.idEq( new Long( p2.getId() ) )).uniqueResult();
+		/*
+		if ( isPlanContractsInverse ) {
+			assertEquals( 1, p.getContracts().size() );
+			c = ( Contract ) p.getContracts().iterator().next();
+			assertEquals( "gail", c.getCustomerName() );
+			if ( isPlanContractsBidirectional ) {
+				assertSame( p, c.getPlans().iterator().next() );
+			}
+			assertEquals( 0, p2.getContracts().size() );
+		}
+		else {
+		*/
+			assertEquals( 0, p.getContracts().size() );
+			assertEquals( 1, p2.getContracts().size() );
+			c = ( Contract ) p2.getContracts().iterator().next();
+			assertEquals( "gail", c.getCustomerName() );
+			if ( isPlanContractsBidirectional ) {
+				assertSame( p2, c.getPlans().iterator().next() );
+			}
+		//}
+		s.delete( p );
+		s.delete( p2 );
+		assertEquals( new Long( 0 ), s.createCriteria( Plan.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	protected void clearCounts() {
+		getSessions().getStatistics().clear();
+	}
+
+	protected void assertInsertCount(int expected) {
+		int inserts = ( int ) getSessions().getStatistics().getEntityInsertCount();
+		assertEquals( "unexpected insert count", expected, inserts );
+	}
+
+	protected void assertUpdateCount(int expected) {
+		int updates = ( int ) getSessions().getStatistics().getEntityUpdateCount();
+		assertEquals( "unexpected update counts", expected, updates );
+	}
+
+	protected void assertDeleteCount(int expected) {
+		int deletes = ( int ) getSessions().getStatistics().getEntityDeleteCount();
+		assertEquals( "unexpected delete counts", expected, deletes );
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithOneToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithOneToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/AbstractEntityWithOneToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,1180 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.util.Iterator;
+
+import org.hibernate.QueryException;
+import org.hibernate.Session;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.junit.functional.FunctionalTestCase;
+
+/**
+ * @author Gail Badner
+ */
+public abstract class AbstractEntityWithOneToManyTest extends FunctionalTestCase {
+	private boolean isContractPartiesInverse;
+	private boolean isContractPartiesBidirectional;
+	private boolean isContractVariationsBidirectional;
+	private boolean isContractVersioned;
+
+	public AbstractEntityWithOneToManyTest(String str) {
+		super(str);
+	}
+
+	public void configure(Configuration cfg) {
+		cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
+		cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
+	}
+
+	public abstract String[] getMappings();
+
+	protected boolean checkUpdateCountsAfterAddingExistingElement() {
+		return true;
+	}
+
+	protected boolean checkUpdateCountsAfterRemovingElementWithoutDelete() {
+		return true;
+	}
+
+	protected void prepareTest() throws Exception {
+		super.prepareTest();
+		isContractPartiesInverse = ( ( SessionFactoryImpl ) getSessions() ).getCollectionPersister( Contract.class.getName() + ".parties" ).isInverse();
+		try {
+			 ( ( SessionFactoryImpl ) getSessions() ).getEntityPersister( Party.class.getName() ).getPropertyType( "contract" );
+			isContractPartiesBidirectional = true;
+		}
+		catch ( QueryException ex) {
+			isContractPartiesBidirectional = false;
+		}
+		try {
+			 ( ( SessionFactoryImpl ) getSessions() ).getEntityPersister( ContractVariation.class.getName() ).getPropertyType( "contract" );
+			isContractVariationsBidirectional = true;
+		}
+		catch ( QueryException ex) {
+			isContractVariationsBidirectional = false;
+		}
+
+		isContractVersioned = ( ( SessionFactoryImpl ) getSessions() ).getEntityPersister( Contract.class.getName() ).isVersioned();
+	}
+
+	public void testUpdateProperty() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		c.addParty( new Party( "party" ) );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		c.setCustomerName( "yogi" );
+		assertEquals( 1, c.getParties().size() );
+		Party party = ( Party ) c.getParties().iterator().next();
+		party.setName( "new party" );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 1, c.getParties().size() );
+		party = ( Party ) c.getParties().iterator().next();
+		assertEquals( "party", party.getName() );
+		if ( isContractPartiesBidirectional ) {
+			assertSame( c, party.getContract() );
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyOneToManyCollectionOfNew() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		c.addParty( new Party( "party" ) );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 1, c.getParties().size() );
+		Party party = ( Party ) c.getParties().iterator().next();
+		assertEquals( "party", party.getName() );
+		if ( isContractPartiesBidirectional ) {
+			assertSame( c, party.getContract() );
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyOneToManyCollectionOfExisting() {
+		clearCounts();
+
+		Party party = new Party( "party" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		c.addParty( party );
+		s = openSession();
+		t = s.beginTransaction();
+		s.save( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		// BUG, should be assertUpdateCount( ! isContractPartiesInverse && isPartyVersioned ? 1 : 0 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 0 , c.getParties().size() );
+			party = ( Party ) s.createCriteria( Party.class ).uniqueResult();
+			assertNull( party.getContract() );
+			s.delete( party );
+		}
+		else {
+			assertEquals( 1 , c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, party.getContract() );
+			}
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testAddNewOneToManyElementToPersistentEntity() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.get( Contract.class, c.getId() );
+		assertEquals( 0, c.getParties().size() );
+		c.addParty( new Party( "party" ) );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 1, c.getParties().size() );
+		Party party = ( Party ) c.getParties().iterator().next();
+		assertEquals( "party", party.getName() );
+		if ( isContractPartiesBidirectional ) {
+			assertSame( c, party.getContract() );
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testAddExistingOneToManyElementToPersistentEntity() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone" );
+		Party party = new Party( "party" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		s.persist( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.get( Contract.class, c.getId() );
+		assertEquals( 0, c.getParties().size() );
+		party = ( Party ) s.get( Party.class, party.getId() );
+		if ( isContractPartiesBidirectional ) {
+			assertNull( party.getContract() );
+		}
+		c.addParty( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		if ( checkUpdateCountsAfterAddingExistingElement() ) {
+			assertUpdateCount( isContractVersioned && ! isContractPartiesInverse ? 1 : 0 );
+		}
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 0, c.getParties().size() );
+			s.delete( party );
+		}
+		else {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, party.getContract() );
+			}
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+	
+	public void testCreateWithEmptyOneToManyCollectionUpdateWithExistingElement() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		s.persist( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.addParty( party );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		if ( checkUpdateCountsAfterAddingExistingElement() ) {
+			assertUpdateCount( isContractVersioned && ! isContractPartiesInverse ? 1 : 0 );
+		}
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 0, c.getParties().size() );
+			s.delete( party );
+		}
+		else {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, party.getContract() );
+			}
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyOneToManyCollectionUpdateWithNewElement() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+		c.addParty( party );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		Party newParty = new Party( "new party" );
+		c.addParty( newParty );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertEquals( 2, c.getParties().size() );
+		for ( Iterator it=c.getParties().iterator(); it.hasNext(); ) {
+			Party aParty = ( Party ) it.next();
+			if ( aParty.getId() == party.getId() ) {
+				assertEquals( "party", aParty.getName() );
+			}
+			else if ( aParty.getId() == newParty.getId() ) {
+				assertEquals( "new party", aParty.getName() );
+			}
+			else {
+				fail( "unknown party" );
+			}
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, aParty.getContract() );
+			}
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionMergeWithExistingElement() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		s.persist( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.addParty( party );
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.merge( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		if ( checkUpdateCountsAfterAddingExistingElement() ) {
+			assertUpdateCount( isContractVersioned && ! isContractPartiesInverse ? 1 : 0 );
+		}
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 0, c.getParties().size() );
+			s.delete( party );
+		}
+		else {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, party.getContract() );
+			}
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testCreateWithNonEmptyOneToManyCollectionMergeWithNewElement() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+		c.addParty( party );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		Party newParty = new Party( "new party" );
+		c.addParty( newParty );
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.merge( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertEquals( 2, c.getParties().size() );
+		for ( Iterator it=c.getParties().iterator(); it.hasNext(); ) {
+			Party aParty = ( Party ) it.next();
+			if ( aParty.getId() == party.getId() ) {
+				assertEquals( "party", aParty.getName() );
+			}
+			else if ( ! aParty.getName().equals( newParty.getName() ) ) {
+				fail( "unknown party:" + aParty.getName() );
+			}
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, aParty.getContract() );
+			}
+		}
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testMoveOneToManyElementToNewEntityCollection() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		c.addParty( new Party( "party" ) );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 1, c.getParties().size() );
+		Party party = ( Party ) c.getParties().iterator().next();
+		assertEquals( "party", party.getName() );
+		if ( isContractPartiesBidirectional ) {
+			assertSame( c, party.getContract() );
+		}
+		c.removeParty( party );
+		Contract c2 = new Contract(null, "david", "phone" );
+		c2.addParty( party );
+		s.save( c2 );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c.getId() ) )).uniqueResult();
+		c2 = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c2.getId() ) )).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, party.getContract() );
+			}
+			assertEquals( 0, c2.getParties().size() );
+		}
+		else {
+			assertEquals( 0, c.getParties().size() );
+			assertEquals( 1, c2.getParties().size() );
+			party = ( Party ) c2.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c2, party.getContract() );
+			}
+		}
+		s.delete(c);
+		s.delete( c2 );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testMoveOneToManyElementToExistingEntityCollection() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		c.addParty( new Party( "party" ) );
+		Contract c2 = new Contract(null, "david", "phone" );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		s.persist( c2 );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 3 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c.getId() ) )).uniqueResult();
+		assertEquals( 1, c.getParties().size() );
+		Party party = ( Party ) c.getParties().iterator().next();
+		assertEquals( "party", party.getName() );
+		if ( isContractPartiesBidirectional ) {
+			assertSame( c, party.getContract() );
+		}
+		c.removeParty( party );
+		c2 = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c2.getId() ) )).uniqueResult();
+		c2.addParty( party );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( isContractVersioned ? 2 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c.getId() ) )).uniqueResult();
+		c2 = (Contract) s.createCriteria( Contract.class ).add( Restrictions.idEq( new Long( c2.getId() ) )).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c, party.getContract() );
+			}
+			assertEquals( 0, c2.getParties().size() );
+		}
+		else {
+			assertEquals( 0, c.getParties().size() );
+			assertEquals( 1, c2.getParties().size() );
+			party = ( Party ) c2.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			if ( isContractPartiesBidirectional ) {
+				assertSame( c2, party.getContract() );
+			}
+		}
+		s.delete(c);
+		s.delete( c2 );
+		assertEquals( new Long( 0 ), s.createCriteria( Contract.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria( Party.class ).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testRemoveOneToManyElementUsingUpdate() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+		c.addParty( party );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.removeParty( party );
+		assertEquals( 0, c.getParties().size() );
+		if ( isContractPartiesBidirectional ) {
+			assertNull( party.getContract() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		s.update( party );
+		t.commit();
+		s.close();
+
+		if ( checkUpdateCountsAfterRemovingElementWithoutDelete() ) {
+			assertUpdateCount( isContractVersioned && ! isContractPartiesInverse ? 1 : 0 );
+		}
+		assertDeleteCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			assertSame( c, party.getContract() );
+		}
+		else {
+			assertEquals( 0, c.getParties().size() );
+			party = ( Party ) s.createCriteria( Party.class ).uniqueResult();
+			if ( isContractPartiesBidirectional ) {
+				assertNull( party.getContract() );
+			}
+			s.delete( party );
+		}
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testRemoveOneToManyElementUsingMerge() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+		c.addParty( party );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.removeParty( party );
+		assertEquals( 0, c.getParties().size() );
+		if ( isContractPartiesBidirectional ) {
+			assertNull( party.getContract() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.merge( c );
+		party = ( Party ) s.merge( party );
+		t.commit();
+		s.close();
+
+		if ( checkUpdateCountsAfterRemovingElementWithoutDelete() ) {
+			assertUpdateCount( isContractVersioned && ! isContractPartiesInverse ? 1 : 0 );
+		}
+		assertDeleteCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		if ( isContractPartiesInverse ) {
+			assertEquals( 1, c.getParties().size() );
+			party = ( Party ) c.getParties().iterator().next();
+			assertEquals( "party", party.getName() );
+			assertSame( c, party.getContract() );
+		}
+		else {
+			assertEquals( 0, c.getParties().size() );
+			party = ( Party ) s.createCriteria( Party.class ).uniqueResult();
+			if ( isContractPartiesBidirectional ) {
+				assertNull( party.getContract() );
+			}
+			s.delete( party );
+		}
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 2 );
+	}
+
+	public void testDeleteOneToManyElement() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+		c.addParty( party );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		c.removeParty( party );
+		s.delete( party );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 0, c.getParties().size() );
+		party = ( Party ) s.createCriteria( Party.class ).uniqueResult();
+		assertNull( party );
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testRemoveOneToManyElementByDelete() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		Party party = new Party( "party" );
+		c.addParty( party );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.removeParty( party );
+		assertEquals( 0, c.getParties().size() );
+		if ( isContractPartiesBidirectional ) {
+			assertNull( party.getContract() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		s.delete( party );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 0, c.getParties().size() );
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testRemoveOneToManyOrphanUsingUpdate() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		ContractVariation cv = new ContractVariation( 1, c );
+		cv.setText( "cv1" );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.getVariations().remove( cv );
+		cv.setContract( null );
+		assertEquals( 0, c.getVariations().size() );
+		if ( isContractVariationsBidirectional ) {
+			assertNull( cv.getContract() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 0, c.getVariations().size() );
+		cv = ( ContractVariation ) s.createCriteria( ContractVariation.class ).uniqueResult();
+		assertNull( cv );
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testRemoveOneToManyOrphanUsingMerge() {
+		Contract c = new Contract( null, "gail", "phone");
+		ContractVariation cv = new ContractVariation( 1, c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		c.getVariations().remove( cv );
+		cv.setContract( null );
+		assertEquals( 0, c.getVariations().size() );
+		if ( isContractVariationsBidirectional ) {
+			assertNull( cv.getContract() );
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.merge( c );
+		cv = ( ContractVariation ) s.merge( cv );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 0, c.getVariations().size() );
+		cv = ( ContractVariation ) s.createCriteria( ContractVariation.class ).uniqueResult();
+		assertNull( cv );
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testDeleteOneToManyOrphan() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gail", "phone");
+		ContractVariation cv = new ContractVariation( 1, c );
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.update( c );
+		c.getVariations().remove( cv );
+		cv.setContract( null );
+		assertEquals( 0, c.getVariations().size() );
+		s.delete( cv );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		assertDeleteCount( 1 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = ( Contract ) s.createCriteria( Contract.class ).uniqueResult();
+		assertEquals( 0, c.getVariations().size() );
+		cv = ( ContractVariation ) s.createCriteria( ContractVariation.class ).uniqueResult();
+		assertNull( cv );
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 1 );
+	}
+
+	public void testOneToManyCollectionOptimisticLockingWithMerge() {
+		clearCounts();
+
+		Contract cOrig = new Contract( null, "gail", "phone");
+		Party partyOrig = new Party( "party" );
+		cOrig.addParty( partyOrig );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(cOrig);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		Contract c = ( Contract ) s.get( Contract.class, cOrig.getId() );
+		Party newParty = new Party( "new party" );
+		c.addParty( newParty );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cOrig.removeParty( partyOrig );
+		try {
+			s.merge( cOrig );
+			assertFalse( isContractVersioned );
+		}
+		catch (StaleObjectStateException ex) {
+			assertTrue( isContractVersioned);
+		}
+		finally {
+			t.rollback();
+		}
+		s.close();
+		
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		s.delete(c);
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertDeleteCount( 3 );
+	}
+
+	public void testOneToManyCollectionOptimisticLockingWithUpdate() {
+		clearCounts();
+
+		Contract cOrig = new Contract( null, "gail", "phone");
+		Party partyOrig = new Party( "party" );
+		cOrig.addParty( partyOrig );
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(cOrig);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 2 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		Contract c = ( Contract ) s.get( Contract.class, cOrig.getId() );
+		Party newParty = new Party( "new party" );
+		c.addParty( newParty );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( isContractVersioned ? 1 : 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cOrig.removeParty( partyOrig );
+		s.update( cOrig );
+		try {
+			t.commit();
+			assertFalse( isContractVersioned );
+		}
+		catch (StaleObjectStateException ex) {
+			assertTrue( isContractVersioned);
+			t.rollback();
+		}
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		s.createQuery( "delete from Party" ).executeUpdate();
+		s.delete( c );
+		assertEquals( new Long( 0 ), s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		assertEquals( new Long( 0 ), s.createCriteria(Party.class).setProjection( Projections.rowCount() ).uniqueResult() );
+		t.commit();
+		s.close();
+	}
+
+	protected void clearCounts() {
+		getSessions().getStatistics().clear();
+	}
+
+	protected void assertInsertCount(int expected) {
+		int inserts = ( int ) getSessions().getStatistics().getEntityInsertCount();
+		assertEquals( "unexpected insert count", expected, inserts );
+	}
+
+	protected void assertUpdateCount(int expected) {
+		int updates = ( int ) getSessions().getStatistics().getEntityUpdateCount();
+		assertEquals( "unexpected update counts", expected, updates );
+	}
+
+	protected void assertDeleteCount(int expected) {
+		int deletes = ( int ) getSessions().getStatistics().getEntityDeleteCount();
+		assertEquals( "unexpected delete counts", expected, deletes );
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Contract.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Contract.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Contract.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,158 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class Contract implements Serializable {
+	
+	private long id;
+	private long version;
+	private String customerName;
+	private String type;
+	private List variations;
+	private Contract parent;
+	private Set subcontracts;
+	private Set plans = new HashSet();
+	private Set parties;
+	private Set infos;
+
+	public Contract() {
+		super();
+	}
+
+	public Contract(Plan plan, String customerName, String type) {
+		plans = new HashSet();
+		if ( plan != null ) {
+			plans.add( plan );
+			plan.getContracts().add( this );
+		}
+		this.customerName = customerName;
+		this.type = type;
+		variations = new ArrayList();
+		subcontracts = new HashSet();
+		parties = new HashSet();
+		infos = new HashSet();
+	}
+
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+	
+	public Set getPlans() {
+		return plans;
+	}
+
+	public void setPlans(Set plans) {
+		this.plans = plans;
+	}
+
+	public String getCustomerName() {
+		return customerName;
+	}
+
+	public void setCustomerName(String customerName) {
+		this.customerName = customerName;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public List getVariations() {
+		return variations;
+	}
+
+	public void setVariations(List variations) {
+		this.variations = variations;
+	}
+
+	public Contract getParent() {
+		return parent;
+	}
+
+	public void setParent(Contract parent) {
+		this.parent = parent;
+	}
+
+	public Set getSubcontracts() {
+		return subcontracts;
+	}
+
+	public void setSubcontracts(Set subcontracts) {
+		this.subcontracts = subcontracts;
+	}
+
+	public void addSubcontract(Contract subcontract) {
+		subcontracts.add( subcontract );
+		subcontract.setParent( this );
+	}
+
+	public Set getParties() {
+		return parties;
+	}
+
+	public void setParties(Set parties) {
+		this.parties = parties;
+	}
+
+	public void addParty(Party party) {
+		parties.add( party );
+		party.setContract( this );
+	}
+
+	public void removeParty(Party party) {
+		parties.remove( party );
+		party.setContract( null );
+	}
+
+	public Set getInfos() {
+		return infos;
+	}
+
+	public void setInfos(Set infos) {
+		this.infos = infos;
+	}
+}


Property changes on: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Contract.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/ContractVariation.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/ContractVariation.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/ContractVariation.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,79 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ContractVariation implements Serializable {
+	
+	private int id;
+	private Contract contract;
+	private String text;
+	private Set infos = new HashSet();
+
+	public Contract getContract() {
+		return contract;
+	}
+
+	public void setContract(Contract contract) {
+		this.contract = contract;
+	}
+
+	public String getText() {
+		return text;
+	}
+
+	public void setText(String text) {
+		this.text = text;
+	}
+
+	public int getId() {
+		return id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public ContractVariation() {
+		super();
+	}
+
+	public ContractVariation(int version, Contract contract) {
+		this.contract = contract;
+		this.id = id;
+		contract.getVariations().add(this);
+	}
+
+	public Set getInfos() {
+		return infos;
+	}
+
+	public void setInfos(Set infos) {
+		this.infos = infos;
+	}
+}


Property changes on: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/ContractVariation.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Info.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Info.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Info.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,66 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.io.Serializable;
+
+public class Info implements Serializable {
+
+	private long id;
+	private String text;
+	private long version;
+
+	public Info() {
+		super();
+	}
+
+	public Info(String text) {
+		this.text = text;
+	}
+
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+
+	public String getText() {
+		return text;
+	}
+
+	public void setText(String text) {
+		this.text = text;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Owner.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Owner.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Owner.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,76 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.io.Serializable;
+
+public class Owner implements Serializable {
+
+	private long id;
+	private long version;
+	private Plan plan;
+	private String name;
+
+	public Owner() {
+		super();
+	}
+
+	public Owner(String name) {
+		this.name = name;
+	}
+
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public Plan getPlan() {
+		return plan;
+	}
+
+	public void setPlan(Plan plan) {
+		this.plan = plan;
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Party.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Party.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Party.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,88 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class Party implements Serializable {
+
+	private long id;
+	private long version;
+	private Contract contract;
+	private String name;
+	private Set infos = new HashSet();
+
+	public Party() {
+		super();
+	}
+
+	public Party(String name) {
+		this.name = name;
+	}
+
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+	
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public Contract getContract() {
+		return contract;
+	}
+
+	public void setContract(Contract contract) {
+		this.contract = contract;
+	}
+
+	public Set getInfos() {
+		return infos;
+	}
+
+	public void setInfos(Set infos) {
+		this.infos = infos;
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Plan.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Plan.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/Plan.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,131 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class Plan implements Serializable {
+
+	private long id;
+	private long version;
+	private String description;
+	private Set contracts;
+	private Set infos;
+	private Owner owner;
+
+	public Plan() {
+		this( null );
+	}
+
+	public Plan(String description) {
+		this.description = description;
+		contracts = new HashSet();
+		infos = new HashSet();
+	}
+
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public Set getContracts() {
+		return contracts;
+	}
+
+	public void setContracts(Set contracts) {
+		this.contracts = contracts;
+	}
+
+	public void addContract(Contract contract) {
+		if ( ! contracts.add( contract ) ) {
+			return;
+		}
+		if ( contract.getParent() != null ) {
+			addContract( contract.getParent() );
+		}
+		contract.getPlans().add( this );
+		for ( Iterator it=contract.getSubcontracts().iterator(); it.hasNext(); ) {
+			Contract sub = ( Contract ) it.next();
+			addContract( sub );
+		}
+	}
+
+	public void removeContract(Contract contract) {
+		if ( contract.getParent() != null ) {
+			contract.getParent().getSubcontracts().remove( contract );
+			contract.setParent( null );			
+		}
+		removeSubcontracts( contract );
+		contract.getPlans().remove( this );
+		contracts.remove( contract );
+	}
+
+	public void removeSubcontracts(Contract contract) {
+		for ( Iterator it=contract.getSubcontracts().iterator(); it.hasNext(); ) {
+			Contract sub = ( Contract ) it.next();
+			removeSubcontracts( sub );
+			sub.getPlans().remove( this );
+			contracts.remove( sub );
+		}
+	}
+
+	public Set getInfos() {
+		return infos;
+	}
+
+	public void setInfos(Set infos) {
+		this.infos = infos;
+	}
+
+	public Owner getOwner() {
+		return owner;
+	}
+
+	public void setOwner(Owner owner) {
+		this.owner = owner;
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="true" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <many-to-one name="contract" not-null="false"/>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="true" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" />
+        <set name="subcontracts" inverse="true"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="false" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" inverse="true"  mutable="true" cascade="all" fetch="join">
+            <key column="contract"/>
+            <one-to-many class="Party"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" not-null="false"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationOneToManyJoin.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationOneToManyJoin.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationOneToManyJoin.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="true" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+        <join table="contract_party"
+            inverse="false"
+            optional="true">
+            <key column="party"/>
+            <many-to-one name="contract"
+                column="contract"
+                not-null="true"/>
+        </join>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="true" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" />
+        <set name="subcontracts" inverse="true"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="false" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" table="contract_party" inverse="true"  mutable="true" cascade="all">
+            <key column="contract"/>
+            <many-to-many column="party" unique="true" class="Party"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" not-null="false"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for readonly.entitywithmutablecollection classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="true" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <many-to-one name="contract" not-null="false"/>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+        <version name="version" column="VERS" type="long" />
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="true" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" />
+        <set name="subcontracts" inverse="true"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="false" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" inverse="true"  mutable="true" cascade="all" fetch="join">
+            <key column="contract"/>
+            <one-to-many class="Party"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" not-null="false"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+           <key column="contractvariation"/>
+           <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersionedOneToManyJoin.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersionedOneToManyJoin.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/ContractVariationVersionedOneToManyJoin.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for readonly.entitywithmutablecollection classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="true" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+        <join table="contract_party"
+            inverse="false"
+            optional="true">
+            <key column="party"/>
+            <many-to-one name="contract"
+                column="contract"
+                not-null="true"/>
+        </join>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+        <version name="version" column="VERS" type="long" />
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="true" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" />
+        <set name="subcontracts" inverse="true"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="false" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" table="contract_party" inverse="true"  mutable="true" cascade="all">
+            <key column="contract"/>
+            <many-to-many column="party" unique="true" class="Party"/>
+        </set>
+        <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" not-null="false"/>
+       <set name="infos" inverse="true"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseManyToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseManyToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseManyToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,49 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithManyToManyTest;
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithInverseManyToManyTest extends AbstractEntityWithManyToManyTest {
+
+	public EntityWithInverseManyToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithInverseManyToManyTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyJoinTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyJoinTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyJoinTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithInverseOneToManyJoinTest extends AbstractEntityWithOneToManyTest {
+
+	public EntityWithInverseOneToManyJoinTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariationOneToManyJoin.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithInverseOneToManyJoinTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/EntityWithInverseOneToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithInverseOneToManyTest extends AbstractEntityWithOneToManyTest {
+
+	public EntityWithInverseOneToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariation.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithInverseOneToManyTest.class );
+	}
+	
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseManyToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseManyToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseManyToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,49 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithManyToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class VersionedEntityWithInverseManyToManyTest extends AbstractEntityWithManyToManyTest {
+
+	public VersionedEntityWithInverseManyToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithInverseManyToManyTest.class );
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyFailureExpectedTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyFailureExpectedTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyFailureExpectedTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,105 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+/**
+ * @author Gail Badner
+ *
+ * These tests reproduce HHH-4992.
+ */
+public class VersionedEntityWithInverseOneToManyFailureExpectedTest extends AbstractEntityWithOneToManyTest {
+
+	public VersionedEntityWithInverseOneToManyFailureExpectedTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithInverseOneToManyFailureExpectedTest.class );
+	}
+
+	public void testAddExistingOneToManyElementToPersistentEntity() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"AddExistingOneToManyElementToPersistentEntity"
+		);
+	}
+
+	public void testAddExistingOneToManyElementToPersistentEntityFailureExpected() {
+		super.testAddExistingOneToManyElementToPersistentEntity();
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionUpdateWithExistingElement() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"CreateWithEmptyOneToManyCollectionUpdateWithExistingElement"
+		);
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionUpdateWithExistingElementFailureExpected() {
+		super.testCreateWithEmptyOneToManyCollectionUpdateWithExistingElement();
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionMergeWithExistingElement() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"CreateWithEmptyOneToManyCollectionMergeWithExistingElement"
+		);
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionMergeWithExistingElementFailureExpected() {
+		super.testCreateWithEmptyOneToManyCollectionMergeWithExistingElement();
+	}
+
+	public void testRemoveOneToManyElementUsingUpdate() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"RemoveOneToManyElementUsingUpdate"
+		);
+	}
+
+	public void testRemoveOneToManyElementUsingUpdateFailureExpected() {
+		super.testRemoveOneToManyElementUsingUpdate();
+	}
+
+	public void testRemoveOneToManyElementUsingMerge() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"RemoveOneToManyElementUsingMerge" 
+		);
+	}
+
+	public void testRemoveOneToManyElementUsingMergeFailureExpected() {
+		super.testRemoveOneToManyElementUsingMerge();
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinFailureExpectedTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinFailureExpectedTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinFailureExpectedTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,104 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class VersionedEntityWithInverseOneToManyJoinFailureExpectedTest extends AbstractEntityWithOneToManyTest {
+
+	public VersionedEntityWithInverseOneToManyJoinFailureExpectedTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariationVersionedOneToManyJoin.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithInverseOneToManyJoinFailureExpectedTest.class );
+	}
+
+	public void testAddExistingOneToManyElementToPersistentEntity() {
+		reportSkip(
+				"known to fail with inverse collection",
+				"AddExistingOneToManyElementToPersistentEntity"
+		);
+	}
+
+	public void testAddExistingOneToManyElementToPersistentEntityFailureExpected() {
+		super.testAddExistingOneToManyElementToPersistentEntity();
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionUpdateWithExistingElement() {
+		reportSkip(
+				"known to fail with inverse collection",
+				"CreateWithEmptyOneToManyCollectionUpdateWithExistingElement"
+		);
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionUpdateWithExistingElementFailureExpected() {
+		super.testCreateWithEmptyOneToManyCollectionUpdateWithExistingElement();
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionMergeWithExistingElement() {
+		reportSkip(
+				"known to fail with versioned entity with inverse one-to-many collection",
+				"CreateWithEmptyOneToManyCollectionMergeWithExistingElement"
+		);
+	}
+
+	public void testCreateWithEmptyOneToManyCollectionMergeWithExistingElementFailureExpected() {
+		super.testCreateWithEmptyOneToManyCollectionMergeWithExistingElement();
+	}
+
+	public void testRemoveOneToManyElementUsingUpdate() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"RemoveOneToManyElementUsingUpdate"
+		);
+	}
+
+	public void testRemoveOneToManyElementUsingUpdateFailureExpected() {
+		super.testRemoveOneToManyElementUsingUpdate();
+	}
+
+	public void testRemoveOneToManyElementUsingMerge() {
+		reportSkip(
+				"known to fail with versioned entity with inverse collection",
+				"RemoveOneToManyElementUsingMerge"
+		);
+	}
+
+	public void testRemoveOneToManyElementUsingMergeFailureExpected() {
+		super.testRemoveOneToManyElementUsingMerge();
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyJoinTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,59 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ *
+ * These tests reproduce HHH-4992.
+ */
+public class VersionedEntityWithInverseOneToManyJoinTest extends AbstractEntityWithOneToManyTest {
+
+	public VersionedEntityWithInverseOneToManyJoinTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariationVersionedOneToManyJoin.hbm.xml" };
+	}
+
+	protected boolean checkUpdateCountsAfterAddingExistingElement() {
+		return false;
+	}
+
+	protected boolean checkUpdateCountsAfterRemovingElementWithoutDelete() {
+		return false;
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithInverseOneToManyJoinTest.class );
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/inverse/VersionedEntityWithInverseOneToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,55 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.inverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+/**
+ * @author Gail Badner
+ */
+public class VersionedEntityWithInverseOneToManyTest extends AbstractEntityWithOneToManyTest {
+
+	public VersionedEntityWithInverseOneToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/inverse/ContractVariationVersioned.hbm.xml" };
+	}
+
+	protected boolean checkUpdateCountsAfterAddingExistingElement() {
+		return false;
+	}
+
+	protected boolean checkUpdateCountsAfterRemovingElementWithoutDelete() {
+		return false;
+	}
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithInverseOneToManyTest.class );
+	}
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariation.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariation.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariation.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="false" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <many-to-one name="contract" update="false" insert="false" not-null="false"/>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="false" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" update="false" insert="false"/>
+        <set name="subcontracts" inverse="false"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="true" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" inverse="false"  mutable="true" cascade="all" fetch="join">
+            <key column="contract"/>
+            <one-to-many class="Party"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" insert="false" update="false" not-null="false"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationOneToManyJoin.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationOneToManyJoin.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationOneToManyJoin.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="false" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+        <join table="contract_party"
+            inverse="true"
+            optional="true">
+            <key column="party"/>
+            <many-to-one name="contract"
+                column="contract"
+                not-null="true"/>
+        </join>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="false" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" update="false" insert="false"/>
+        <set name="subcontracts" inverse="false"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="true" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" table="contract_party" inverse="false"  mutable="true" cascade="all">
+            <key column="contract"/>
+            <many-to-many column="party" unique="true" class="Party"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" insert="false" update="false" not-null="false"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationUnidir.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationUnidir.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationUnidir.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="text"/>        
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="false" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="false" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" update="false" insert="false"/>
+        <set name="subcontracts" inverse="false"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="parties" inverse="false"  mutable="true" cascade="all" fetch="join">
+            <key column="contract"/>
+            <one-to-many class="Party"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" insert="false" update="false" not-null="false"/>
+       <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersioned.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersioned.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersioned.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="text"/>
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="false" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <many-to-one name="contract" update="false" insert="false" not-null="false"/>
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+        <version name="version" column="VERS" type="long" />
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="false" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" update="false" insert="false"/>
+        <set name="subcontracts" inverse="false"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="true" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" inverse="false"  mutable="true" cascade="all" fetch="join">
+            <key column="contract"/>
+            <one-to-many class="Party"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" insert="false" update="false" not-null="false"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersionedOneToManyJoin.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersionedOneToManyJoin.hbm.xml	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/ContractVariationVersionedOneToManyJoin.hbm.xml	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!-- 
+
+  Test for immutable classes/collections.
+     
+-->
+
+<hibernate-mapping package="org.hibernate.test.immutable.entitywithmutablecollection">
+    <class name="Info" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="text"/>
+    </class>
+
+    <class name="Plan" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="description" not-null="true"/>
+        <set name="contracts" table="plan_contract" inverse="false" mutable="true" cascade="all" fetch="join">
+            <key column="plan"/>
+            <many-to-many column="contract" class="Contract"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="plan"/>
+            <one-to-many class="Info"/>
+        </set>
+    </class>
+
+    <class name="Party" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+        <version name="version" column="VERS" type="long" />
+        <property name="name" not-null="true"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="party"/>
+            <one-to-many class="Info"/>
+        </set>
+        <join table="contract_party"
+            inverse="true"
+            optional="true">
+            <key column="party"/>
+            <many-to-one name="contract"
+                column="contract"
+                not-null="true"/>
+        </join>
+    </class>
+
+	<class name="Contract" mutable="false">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+        <version name="version" column="VERS" type="long" />
+		<property name="customerName" not-null="true"/>
+		<property name="type" not-null="true"/>
+		<bag name="variations" inverse="false" order-by="id asc"
+				mutable="true" cascade="all-delete-orphan" fetch="join">
+			<key column="contract"/>
+			<one-to-many class="ContractVariation"/>
+		</bag>
+        <many-to-one name="parent" update="false" insert="false"/>
+        <set name="subcontracts" inverse="false"
+                mutable="true" cascade="all" fetch="join">
+            <key column="parent"/>
+            <one-to-many class="Contract"/>
+        </set>
+        <set name="plans" table="plan_contract" inverse="true" mutable="true" cascade="none">
+            <key column="contract"/>
+            <many-to-many column="plan" class="Plan"/>
+        </set>
+        <set name="parties" table="contract_party" inverse="false"  mutable="true" cascade="all">
+            <key column="contract"/>
+            <many-to-many column="party" unique="true" class="Party"/>
+        </set>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contract"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+
+	<class name="ContractVariation" mutable="false">
+        <id name="id">
+            <generator class="increment"/>
+        </id>
+		<property name="text" type="text"/>
+        <many-to-one name="contract" insert="false" update="false" not-null="false"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key column="contractvariation"/>
+            <one-to-many class="Info"/>
+        </set>
+	</class>
+	
+</hibernate-mapping>

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithManyToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithNonInverseManyToManyTest extends AbstractEntityWithManyToManyTest {
+
+	public EntityWithNonInverseManyToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariation.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithNonInverseManyToManyTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyUnidirTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyUnidirTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseManyToManyUnidirTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithManyToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithNonInverseManyToManyUnidirTest extends AbstractEntityWithManyToManyTest {
+
+	public EntityWithNonInverseManyToManyUnidirTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariationUnidir.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithNonInverseManyToManyUnidirTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyJoinTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyJoinTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyJoinTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithNonInverseOneToManyJoinTest extends AbstractEntityWithOneToManyTest {
+
+	public EntityWithNonInverseOneToManyJoinTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariationOneToManyJoin.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithNonInverseOneToManyJoinTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithNonInverseOneToManyTest extends AbstractEntityWithOneToManyTest {
+
+	public EntityWithNonInverseOneToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariation.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithNonInverseOneToManyTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyUnidirTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyUnidirTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/EntityWithNonInverseOneToManyUnidirTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithNonInverseOneToManyUnidirTest extends AbstractEntityWithOneToManyTest {
+
+	public EntityWithNonInverseOneToManyUnidirTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariationUnidir.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( EntityWithNonInverseOneToManyUnidirTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseManyToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseManyToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseManyToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithManyToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class VersionedEntityWithNonInverseManyToManyTest extends AbstractEntityWithManyToManyTest {
+
+	public VersionedEntityWithNonInverseManyToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariationVersioned.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithNonInverseManyToManyTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyJoinTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyJoinTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyJoinTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class VersionedEntityWithNonInverseOneToManyJoinTest extends AbstractEntityWithOneToManyTest {
+
+	public VersionedEntityWithNonInverseOneToManyJoinTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariationVersionedOneToManyJoin.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithNonInverseOneToManyJoinTest.class );
+	}
+
+}
\ No newline at end of file

Added: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyTest.java	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/entitywithmutablecollection/noninverse/VersionedEntityWithNonInverseOneToManyTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.immutable.entitywithmutablecollection.noninverse;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.test.immutable.entitywithmutablecollection.AbstractEntityWithOneToManyTest;
+
+
+/**
+ * @author Gail Badner
+ */
+public class VersionedEntityWithNonInverseOneToManyTest extends AbstractEntityWithOneToManyTest {
+
+	public VersionedEntityWithNonInverseOneToManyTest(String str) {
+		super(str);
+	}
+
+	public String[] getMappings() {
+		return new String[] { "immutable/entitywithmutablecollection/noninverse/ContractVariationVersioned.hbm.xml" };
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( VersionedEntityWithNonInverseOneToManyTest.class );
+	}
+
+}
\ No newline at end of file

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java	2010-03-10 10:56:16 UTC (rev 18956)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java	2010-03-10 11:03:08 UTC (rev 18957)
@@ -283,17 +283,17 @@
 		s.getTransaction().commit();
 		s.close();
 
-		assertUpdateCount( 0 );
-		assertInsertCount( 0 );
+		assertUpdateCount( 1 );
+		assertInsertCount( 1 );
 
 		s = openSession();
 		s.beginTransaction();
 		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
 		assertEquals( "parent", parent.getName() );
-		assertEquals( 0, parent.getChildren().size() );
-		assertEquals( 0, parent.getVersion() );
+		assertEquals( 1, parent.getChildren().size() );
+		assertEquals( 1, parent.getVersion() );
 		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
-		assertNull( child );
+		assertNotNull( child );
 		s.delete( parent );
 		s.getTransaction().commit();
 		s.close();
@@ -320,7 +320,7 @@
 		s.getTransaction().commit();
 		s.close();
 
-		assertUpdateCount( 0 );
+		assertUpdateCount( 1 );
 		assertInsertCount( 1 );
 		clearCounts();
 
@@ -330,7 +330,7 @@
 		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
 		assertEquals( parent.getName(), "parent" );
 		assertEquals( 1, parent.getChildren().size() );
-		assertEquals( 0, parent.getVersion() );
+		assertEquals( 1, parent.getVersion() );
 		assertSame( parent, child.getParent() );
 		assertSame( child, parent.getChildren().iterator().next() );
 		assertEquals( 0, child.getVersion() );
@@ -366,7 +366,7 @@
 		s.getTransaction().commit();
 		s.close();
 
-		assertUpdateCount( 0 );
+		assertUpdateCount( 1 );
 		assertInsertCount( 1 );
 		clearCounts();
 
@@ -376,7 +376,7 @@
 		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
 		assertEquals( parent.getName(), "parent" );
 		assertEquals( 1, parent.getChildren().size() );
-		assertEquals( 0, parent.getVersion() );
+		assertEquals( 1, parent.getVersion() );
 		assertSame( parent, child.getParent() );
 		assertSame( child, parent.getChildren().iterator().next() );
 		assertEquals( 0, child.getVersion() );
@@ -414,7 +414,7 @@
 		s.getTransaction().commit();
 		s.close();
 
-		assertUpdateCount( 0 );
+		assertUpdateCount( 1 );
 		assertInsertCount( 1 );
 		clearCounts();
 
@@ -424,7 +424,7 @@
 		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
 		assertEquals( parent.getName(), "parent" );
 		assertEquals( 1, parent.getChildren().size() );
-		assertEquals( 0, parent.getVersion() );
+		assertEquals( 1, parent.getVersion() );
 		assertSame( parent, child.getParent() );
 		assertSame( child, parent.getChildren().iterator().next() );
 		assertEquals( 0, child.getVersion() );
@@ -521,7 +521,7 @@
 		s.close();
 
 		assertUpdateCount( 0 );
-		assertInsertCount( 0 );
+		assertInsertCount( 1 );
 
 		s = openSession();
 		s.beginTransaction();
@@ -530,7 +530,7 @@
 		assertNull( child.getParent() );
 		assertEquals( 0, child.getVersion() );
 		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
-		assertNull( parent );
+		assertNotNull( parent );
 		s.setReadOnly( child, true );
 		s.delete( child );
 		s.getTransaction().commit();



More information about the hibernate-commits mailing list