[hibernate-commits] Hibernate SVN: r18873 - in core/trunk: core/src/main/java/org/hibernate/event/def and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Feb 24 16:20:27 EST 2010


Author: gbadner
Date: 2010-02-24 16:20:26 -0500 (Wed, 24 Feb 2010)
New Revision: 18873

Modified:
   core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java
   core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java
   core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
   core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java
   core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java
   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/ContractVariation.java
   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
Log:
HHH-4809 : Immutable entities added to a session have Status.MANAGED unless loaded by the Session

Modified: core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java	2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -309,6 +309,9 @@
 			loadedState = null;
 		}
 		else {
+			if ( ! persister.isMutable() ) {
+				throw new IllegalStateException( "Cannot make an immutable entity modifiable." );
+			}
 			setStatus( Status.MANAGED );
 			loadedState = getPersister().getPropertyValues( entity, entityMode );
 		}

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java	2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -88,7 +88,7 @@
 
 		EntityEntry newEntry = source.getPersistenceContext().addEntity(
 				object,
-				Status.MANAGED,
+				( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
 				values,
 				key,
 				version,

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java	2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -333,7 +333,7 @@
 		Object version = Versioning.getVersion( values, persister );
 		source.getPersistenceContext().addEntity(
 				entity,
-				Status.MANAGED,
+				( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
 				values,
 				key,
 				version,

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java	2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -126,7 +126,7 @@
 
 			entityEntry = persistenceContext.addEntity(
 					entity,
-					Status.MANAGED,
+					( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
 					persister.getPropertyValues( entity, source.getEntityMode() ),
 					key,
 					version,

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java	2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -194,7 +194,7 @@
 
 		source.getPersistenceContext().addEntity(
 				entity,
-				Status.MANAGED,
+				( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
 				null,
 				new EntityKey( id, persister, source.getEntityMode() ),
 				version,

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-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -124,9 +124,4 @@
 	public void setInfos(Set infos) {
 		this.infos = infos;
 	}
-
-	public void addInfo(Info info) {
-		infos.add( info );
-		info.setContract( this );
-	}
 }

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-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml	2010-02-24 21:20:26 UTC (rev 18873)
@@ -15,7 +15,6 @@
             <generator class="increment"/>
         </id>
         <property name="text"/>        
-        <many-to-one name="contract" not-null="false"/>
     </class>
 
     <class name="Plan" mutable="false">
@@ -27,6 +26,10 @@
             <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">
@@ -36,6 +39,10 @@
         <!-- <many-to-one name="contract" update="false" insert="false"/> -->
         <many-to-one name="contract" not-null="true"/>
         <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">
@@ -64,7 +71,7 @@
             <key column="contract"/>
             <one-to-many class="Party"/>
         </set>
-        <set name="infos" inverse="true"  mutable="true" cascade="all" fetch="join">
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
             <key column="contract"/>
             <one-to-many class="Info"/>
         </set>
@@ -76,6 +83,13 @@
 			<key-property name="version"/>
 		</composite-id>
 		<property name="text" type="text"/>
+        <set name="infos" inverse="false"  mutable="true" cascade="all-delete-orphan">
+            <key>
+                <column name="contract"/>
+                <column name="version"/>
+            </key>
+            <one-to-many class="Info"/>
+        </set>
 	</class>
 	
 </hibernate-mapping>

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java	2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -2,12 +2,15 @@
 package org.hibernate.test.immutable;
 
 import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
 
 public class ContractVariation implements Serializable {
 	
 	private int version;
 	private Contract contract;
 	private String text;
+	private Set infos = new HashSet();
 
 	public Contract getContract() {
 		return contract;
@@ -42,4 +45,12 @@
 		this.version = version;
 		contract.getVariations().add(this);
 	}
+
+	public Set getInfos() {
+		return infos;
+	}
+
+	public void setInfos(Set infos) {
+		this.infos = infos;
+	}
 }

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-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -38,6 +38,7 @@
 import org.hibernate.criterion.Projections;
 import org.hibernate.junit.functional.FunctionalTestCase;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.proxy.HibernateProxy;
 
 /**
  * @author Gavin King
@@ -61,6 +62,126 @@
 		return new FunctionalTestClassTestSuite( ImmutableTest.class );
 	}
 
+	public void testChangeImmutableEntityProxyToModifiable() {
+		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");
+
+		clearCounts();
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 3 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertTrue( s.isReadOnly( c ) );
+		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" );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
+
+		try {
+			assertTrue( c instanceof HibernateProxy );
+			s.setReadOnly( c, false );
+		}
+		catch (IllegalStateException ex) {
+			// expected
+		}
+		finally {
+			t.rollback();
+			s.close();
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		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 testChangeImmutableEntityToModifiable() {
+		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");
+
+		clearCounts();
+
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 3 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+		assertTrue( s.isReadOnly( c ) );
+		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" );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
+
+		try {
+			assertTrue( c instanceof HibernateProxy );
+			s.setReadOnly( ( ( HibernateProxy ) c ).getHibernateLazyInitializer().getImplementation(), false );
+		}
+		catch (IllegalStateException ex) {
+			// expected
+		}
+		finally {
+			t.rollback();
+			s.close();
+		}
+
+		s = openSession();
+		t = s.beginTransaction();
+		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 testPersistImmutable() {
 		Contract c = new Contract( null, "gavin", "phone");
 		ContractVariation cv1 = new ContractVariation(1, c);
@@ -73,10 +194,9 @@
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
 		s.persist(c);
-		// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		t.commit();
 		s.close();
 
@@ -87,7 +207,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -96,7 +215,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		s.delete(c);
@@ -121,10 +239,9 @@
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
 		s.persist(c);
-		// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		c.setCustomerName( "gail" );
 		t.commit();
 		s.close();
@@ -136,7 +253,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -145,7 +261,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		s.delete(c);
@@ -169,10 +284,9 @@
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
 		s.save(c);
-		// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		t.commit();
 		s.close();
 
@@ -183,7 +297,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -192,7 +305,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		s.delete(c);
@@ -216,10 +328,9 @@
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
 		s.saveOrUpdate(c);
-		// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		t.commit();
 		s.close();
 
@@ -230,7 +341,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -239,7 +349,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		s.delete(c);
@@ -263,10 +372,9 @@
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
 		s.persist(c);
-		// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		t.commit();
 		s.close();
 
@@ -277,12 +385,10 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		c.setCustomerName("foo bar");
 		cv1 = (ContractVariation) c.getVariations().iterator().next();
 		cv1.setText("blah blah");
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertFalse( s.contains( cv2 ) );
 		t.commit();
@@ -298,7 +404,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -307,7 +412,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		s.delete(c);
@@ -331,10 +435,9 @@
 		Session s = openSession();
 		Transaction t = s.beginTransaction();
 		s.persist(c);
-		// c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		c.setCustomerName( "Sherman" );
 		t.commit();
 		s.close();
@@ -346,12 +449,10 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		c.setCustomerName("foo bar");
 		cv1 = (ContractVariation) c.getVariations().iterator().next();
 		cv1.setText("blah blah");
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertFalse( s.contains( cv2 ) );
 		t.commit();
@@ -367,7 +468,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -376,7 +476,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		s.delete(c);
@@ -410,7 +509,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.createCriteria(Contract.class).uniqueResult();
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -419,7 +517,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		c.setCustomerName( "Sherman" );
@@ -454,7 +551,6 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = (Contract) s.get( Contract.class, c.getId() );
-		// c was loaded into s by hibernate, so it should be read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertEquals( c.getCustomerName(), "gavin" );
 		assertEquals( c.getVariations().size(), 2 );
@@ -463,7 +559,6 @@
 		assertEquals( cv1.getText(), "expensive" );
 		cv2 = (ContractVariation) it.next();
 		assertEquals( cv2.getText(), "more expensive" );
-		// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		c.setCustomerName( "Sherman" );
@@ -559,15 +654,17 @@
 		t = s.beginTransaction();
 		c.setCustomerName("foo bar");
 		s.update( c );
-		// c was not loaded into s by hibernate, so it should be modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.contains( cv1 ) );
-		assertFalse( s.contains( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		for ( Iterator it = c.getVariations().iterator(); it.hasNext(); ) {
+			assertTrue( s.contains( it.next() ) );
+		}
 		t.commit();
-		// c, cv1, and cv2 were not loaded into s by hibernate, so they are modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );		
+		assertTrue( s.isReadOnly( c ) );
+		for ( Iterator it = c.getVariations().iterator(); it.hasNext(); ) {
+			ContractVariation cv = ( ContractVariation ) it.next();
+			assertTrue( s.contains( cv ) );
+			assertTrue( s.isReadOnly( cv ) );
+		}
 		s.close();
 
 		assertUpdateCount( 0 );
@@ -615,14 +712,13 @@
 		cv1 = (ContractVariation) c.getVariations().iterator().next();
 		cv1.setText("blah blah");
 		s.update( c );
-		// c was not loaded into s by hibernate, so it should be modifiable
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.contains( cv1 ) );
-		assertFalse( s.contains( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.contains( cv1 ) );
+		assertTrue( s.contains( cv2 ) );
 		t.commit();
-		assertFalse( s.isReadOnly( c ) );
-		assertFalse( s.isReadOnly( cv1 ) );
-		assertFalse( s.isReadOnly( cv2 ) );
+		assertTrue( s.isReadOnly( c ) );
+		assertTrue( s.isReadOnly( cv1 ) );
+		assertTrue( s.isReadOnly( cv2 ) );
 		s.close();
 
 		assertUpdateCount( 0 );
@@ -667,8 +763,9 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c.getVariations().add( new ContractVariation(3, c) );
+		s.update( c );
 		try {
-			s.update( c );
+			t.commit();
 			fail( "should have failed because reassociated object has a dirty collection");
 		}
 		catch ( HibernateException ex ) {
@@ -722,13 +819,11 @@
 		s = openSession();
 		t = s.beginTransaction();
 		c = ( Contract ) s.merge( c );
-		// c was loaded into s by hibernate in the merge process, so it is read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertTrue( Hibernate.isInitialized( c.getVariations() ) );
 		Iterator it = c.getVariations().iterator();
 		cv1 = (ContractVariation) it.next();
 		cv2 = (ContractVariation) it.next();
-		// cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
 		assertTrue( s.isReadOnly( cv1 ) );
 		assertTrue( s.isReadOnly( cv2 ) );
 		t.commit();
@@ -778,13 +873,11 @@
 		t = s.beginTransaction();
 		c.setCustomerName("foo bar");
 		c = ( Contract ) s.merge( c );
-		// c was loaded into s by hibernate in the merge process, so it is read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertTrue( Hibernate.isInitialized( c.getVariations() ) );
 		Iterator it = c.getVariations().iterator();
 		cv1 = (ContractVariation) it.next();
 		cv2 = (ContractVariation) it.next();
-		// cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertTrue( s.isReadOnly( c ) );
 		t.commit();
@@ -836,13 +929,11 @@
 		cv1 = (ContractVariation) c.getVariations().iterator().next();
 		cv1.setText("blah blah");
 		c = ( Contract ) s.merge( c );
-		// c was loaded into s by hibernate in the merge process, so it is read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertTrue( Hibernate.isInitialized( c.getVariations() ) );
 		Iterator it = c.getVariations().iterator();
 		cv1 = (ContractVariation) it.next();
 		cv2 = (ContractVariation) it.next();
-		// cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
 		assertTrue( s.isReadOnly( c ) );
 		assertTrue( s.isReadOnly( c ) );
 		t.commit();
@@ -925,6 +1016,212 @@
 		assertDeleteCount( 3 );		
 	}
 
+	public void testNewEntityViaImmutableEntityWithImmutableCollectionUsingSaveOrUpdate() {
+		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);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 3 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cv1.getInfos().add( new Info( "cv1 info" ) );
+		s.saveOrUpdate( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+
+		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" );
+		assertEquals( 1, cv1.getInfos().size() );
+		assertEquals( "cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		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 testNewEntityViaImmutableEntityWithImmutableCollectionUsingMerge() {
+		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);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 3 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cv1.getInfos().add( new Info( "cv1 info" ) );
+		s.merge( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 1 );
+		assertUpdateCount( 0 );
+
+		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" );
+		assertEquals( 1, cv1.getInfos().size() );
+		assertEquals( "cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		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 testUpdatedEntityViaImmutableEntityWithImmutableCollectionUsingSaveOrUpdate() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gavin", "phone");
+		ContractVariation cv1 = new ContractVariation(1, c);
+		cv1.setText("expensive");
+		Info cv1Info = new Info( "cv1 info" );
+		cv1.getInfos().add( cv1Info );
+		ContractVariation cv2 = new ContractVariation(2, c);
+		cv2.setText("more expensive");
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 4 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cv1Info.setText( "new cv1 info" );
+		s.saveOrUpdate( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( 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" );
+		assertEquals( 1, cv1.getInfos().size() );
+		assertEquals( "new cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		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 testUpdatedEntityViaImmutableEntityWithImmutableCollectionUsingMerge() {
+		clearCounts();
+
+		Contract c = new Contract( null, "gavin", "phone");
+		ContractVariation cv1 = new ContractVariation(1, c);
+		cv1.setText("expensive");
+		Info cv1Info = new Info( "cv1 info" );
+		cv1.getInfos().add( cv1Info );
+		ContractVariation cv2 = new ContractVariation(2, c);
+		cv2.setText("more expensive");
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		s.persist(c);
+		t.commit();
+		s.close();
+
+		assertInsertCount( 4 );
+		assertUpdateCount( 0 );
+		clearCounts();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cv1Info.setText( "new cv1 info" );
+		s.merge( c );
+		t.commit();
+		s.close();
+
+		assertInsertCount( 0 );
+		assertUpdateCount( 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" );
+		assertEquals( 1, cv1.getInfos().size() );
+		assertEquals( "new cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+		cv2 = (ContractVariation) it.next();
+		assertEquals( cv2.getText(), "more expensive" );
+		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-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -7,7 +7,6 @@
 
 	private long id;
 	private String text;
-	private Contract contract;
 
 	public Info() {
 		super();
@@ -32,12 +31,4 @@
 	public void setId(long id) {
 		this.id = id;
 	}
-
-	public Contract getContract() {
-		return contract;
-	}
-
-	public void setContract(Contract contract ) {
-		this.contract = contract;
-	}
 }
\ No newline at end of file

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-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -12,6 +12,7 @@
 	private long id;
 	private Contract contract;
 	private String name;
+	private Set infos = new HashSet();
 
 	public Party() {
 		super();
@@ -44,4 +45,12 @@
 	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

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-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java	2010-02-24 21:20:26 UTC (rev 18873)
@@ -11,6 +11,7 @@
 	private long id;
 	private String description;
 	private Set contracts;
+	private Set infos;
 
 	public Plan() {
 		this( null );
@@ -19,6 +20,7 @@
 	public Plan(String description) {
 		this.description = description;
 		contracts = new HashSet();
+		infos = new HashSet();
 	}
 
 	public long getId() {
@@ -77,4 +79,12 @@
 			contracts.remove( sub );
 		}
 	}
+
+	public Set getInfos() {
+		return infos;
+	}
+
+	public void setInfos(Set infos) {
+		this.infos = infos;
+	}
 }
\ No newline at end of file



More information about the hibernate-commits mailing list