Java Mailing List Archive

http://www.gg3721.com/

Home » Hibernate Commits List »

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

hibernate-commits

2010-03-10


Author LoginPost Reply
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)
@@(protected) @@
public class Contract implements Serializable {
 
 private long id;
+  private long version;
 private String customerName;
 private String type;
 private List variations;
@@(protected) @@

 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;
@@(protected) @@
   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)
@@(protected) @@
        <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"/>
@@(protected) @@
   <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)
@@(protected) @@
   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)
@@(protected) @@

 private long id;
 private String text;
+  private long version;

 public Info() {
   super();
@@(protected) @@
   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)
@@(protected) @@
public class Party implements Serializable {

 private long id;
+  private long version;
 private Contract contract;
 private String name;
 private Set infos = new HashSet();
@@(protected) @@
   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)
@@(protected) @@
public class Plan implements Serializable {

 private long id;
+  private long version;
 private String description;
 private Set contracts;
 private Set infos;
@@(protected) @@
   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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+<?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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
+/*
+ * 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)
@@(protected) @@
   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();
@@(protected) @@
   s.getTransaction().commit();
   s.close();

-    assertUpdateCount( 0 );
+    assertUpdateCount( 1 );
   assertInsertCount( 1 );
   clearCounts();

@@(protected) @@
   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() );
@@(protected) @@
   s.getTransaction().commit();
   s.close();

-    assertUpdateCount( 0 );
+    assertUpdateCount( 1 );
   assertInsertCount( 1 );
   clearCounts();

@@(protected) @@
   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() );
@@(protected) @@
   s.getTransaction().commit();
   s.close();

-    assertUpdateCount( 0 );
+    assertUpdateCount( 1 );
   assertInsertCount( 1 );
   clearCounts();

@@(protected) @@
   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() );
@@(protected) @@
   s.close();

   assertUpdateCount( 0 );
-    assertInsertCount( 0 );
+    assertInsertCount( 1 );

   s = openSession();
   s.beginTransaction();
@@(protected) @@
   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();

_______________________________________________
hibernate-commits mailing list
hibernate-commits@(protected)
https://lists.jboss.org/mailman/listinfo/hibernate-commits
©2008 gg3721.com - Jax Systems, LLC, U.S.A.