[hibernate-commits] Hibernate SVN: r16512 - in core/branches/Branch_3_3: testsuite/src/test/java/org/hibernate/test/immutable and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue May 5 21:18:43 EDT 2009


Author: gbadner
Date: 2009-05-05 21:18:43 -0400 (Tue, 05 May 2009)
New Revision: 16512

Added:
   core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
   core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.hbm.xml
   core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.java
Modified:
   core/branches/Branch_3_3/core/src/main/java/org/hibernate/event/def/DefaultMergeEventListener.java
   core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
   core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java
Log:
HHH-3662 : Merging read-only entities causes AssertionError


Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/event/def/DefaultMergeEventListener.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/event/def/DefaultMergeEventListener.java	2009-05-06 00:44:48 UTC (rev 16511)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/event/def/DefaultMergeEventListener.java	2009-05-06 01:18:43 UTC (rev 16512)
@@ -93,8 +93,8 @@
 				// TODO: cache the entity name somewhere so that it is available to this exception
 				// entity name will not be available for non-POJO entities
 			}
-			if ( entry.getStatus() != Status.MANAGED ) {
-				throw new AssertionFailure( "Merged entity does not have status set to MANAGED; "+entry+" status="+entry.getStatus() );
+			if ( entry.getStatus() != Status.MANAGED && entry.getStatus() != Status.READ_ONLY ) {
+				throw new AssertionFailure( "Merged entity does not have status set to MANAGED or READ_ONLY; "+entry+" status="+entry.getStatus() );
 			}
 		}
 	}

Modified: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java	2009-05-06 00:44:48 UTC (rev 16511)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java	2009-05-06 01:18:43 UTC (rev 16512)
@@ -1,8 +1,35 @@
 //$Id: ImmutableTest.java 10977 2006-12-12 23:28:04Z steve.ebersole at jboss.com $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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;
 
+import java.util.Iterator;
+
 import junit.framework.Test;
 
+import org.hibernate.HibernateException;
 import org.hibernate.Session;
 import org.hibernate.Transaction;
 import org.hibernate.criterion.Projections;
@@ -53,8 +80,84 @@
 		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" );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		t.commit();
+		s.close();
+	}
+
+	public void testImmutableParentEntityWithUpdate() {
+		Contract c = new Contract("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();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c.setCustomerName("foo bar");
+		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" );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		t.commit();
+		s.close();
+	}
+
+	public void testImmutableChildEntityWithUpdate() {
+		Contract c = new Contract("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();
+
+		s = openSession();
+		t = s.beginTransaction();
 		cv1 = (ContractVariation) c.getVariations().iterator().next();
+		cv1.setText("blah blah");
+		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" );
 		s.delete(c);
 		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
 		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
@@ -62,5 +165,166 @@
 		s.close();
 	}
 
+	public void testImmutableCollectionWithUpdate() {
+		Contract c = new Contract("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();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c.getVariations().add( new ContractVariation(3, c) );
+		try {
+			s.update( c );
+			fail( "should have failed because reassociated object has a dirty collection");
+		}
+		catch ( HibernateException ex ) {
+			// expected
+		}
+		finally {
+			t.rollback();
+			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" );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		t.commit();
+		s.close();
+	}
+
+	public void testImmutableParentEntityWithMerge() {
+		Contract c = new Contract("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();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c.setCustomerName("foo bar");
+		s.merge( 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" );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		t.commit();
+		s.close();
+	}
+
+	public void testImmutableChildEntityWithMerge() {
+		Contract c = new Contract("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();
+
+		s = openSession();
+		t = s.beginTransaction();
+		cv1 = (ContractVariation) c.getVariations().iterator().next();
+		cv1.setText("blah blah");
+		s.merge( 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" );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		t.commit();
+		s.close();
+	}
+
+	public void testImmutableCollectionWithMerge() {
+		Contract c = new Contract("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();
+
+		s = openSession();
+		t = s.beginTransaction();
+		c.getVariations().add( new ContractVariation(3, c) );
+		s.merge( c );
+		try {
+			t.commit();
+			fail( "should have failed because an immutable collection was changed");
+		}
+		catch ( HibernateException ex ) {
+			// expected
+			t.rollback();
+		}
+		finally {
+			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" );
+		s.delete(c);
+		assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
+		t.commit();
+		s.close();
+	}
 }
 

Modified: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java	2009-05-06 00:44:48 UTC (rev 16511)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyTest.java	2009-05-06 01:18:43 UTC (rev 16512)
@@ -1,4 +1,28 @@
 //$Id: ReadOnlyTest.java 10977 2006-12-12 23:28:04Z steve.ebersole at jboss.com $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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.readonly;
 
 import java.math.BigDecimal;
@@ -148,5 +172,39 @@
 		s.getTransaction().commit();
 		s.close();
 	}
+
+	public void testMergeWithReadOnlyEntity() {
+
+		Session s = openSession();
+		s.setCacheMode(CacheMode.IGNORE);
+		Transaction t = s.beginTransaction();
+		DataPoint dp = new DataPoint();
+		dp.setX( new BigDecimal(0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
+		dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
+		s.save(dp);
+		t.commit();
+		s.close();
+
+		dp.setDescription( "description" );
+
+		s = openSession();
+		s.setCacheMode(CacheMode.IGNORE);
+		t = s.beginTransaction();
+		DataPoint dpManaged = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
+		s.setReadOnly( dpManaged, true );
+		DataPoint dpMerged = ( DataPoint ) s.merge( dp );
+		assertSame( dpManaged, dpMerged );
+		t.commit();
+		s.close();
+
+		s = openSession();
+		t = s.beginTransaction();
+		dpManaged = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
+		assertNull( dpManaged.getDescription() );
+		s.delete( dpManaged );
+		t.commit();
+		s.close();
+
+	}
 }
 

Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java	                        (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java	2009-05-06 01:18:43 UTC (rev 16512)
@@ -0,0 +1,481 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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.readonly;
+
+import junit.framework.Test;
+
+import org.hibernate.Session;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+
+/**
+ * @author Gail Badner
+ */
+public class ReadOnlyVersionedNodesTest extends FunctionalTestCase {
+
+	public ReadOnlyVersionedNodesTest(String str) {
+		super( str );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "readonly/VersionedNode.hbm.xml" };
+	}
+
+	public String getCacheConcurrencyStrategy() {
+		return null;
+	}
+
+	public void configure(Configuration cfg) {
+		cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
+		cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ReadOnlyVersionedNodesTest.class );
+	}
+
+	public void testSetReadOnlyTrueAndFalse() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode node = new VersionedNode( "node", "node" );
+		s.persist( node );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		s = openSession();
+
+		s.beginTransaction();
+		node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
+		s.setReadOnly( node, true );
+		node.setName( "node-name" );
+		s.getTransaction().commit();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 0 );
+
+		// the changed name is still in node
+		assertEquals( "node-name", node.getName() );
+
+		s.beginTransaction();
+		node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
+		// the changed name is still in the session
+		assertEquals( "node-name", node.getName() );
+		s.refresh( node );
+		// after refresh, the name reverts to the original value
+		assertEquals( "node", node.getName() );
+		node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
+		assertEquals( "node", node.getName() );
+		s.getTransaction().commit();
+
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 0 );
+
+		s = openSession();
+		s.beginTransaction();
+		node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
+		assertEquals( "node", node.getName() );
+		s.setReadOnly( node, true );
+		node.setName( "diff-node-name" );
+		s.flush();
+		assertEquals( "diff-node-name", node.getName() );
+		s.refresh( node );
+		assertEquals( "node", node.getName() );
+		s.setReadOnly( node, false );
+		node.setName( "diff-node-name" );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 1 );
+		assertInsertCount( 0 );
+
+		s = openSession();
+		s.beginTransaction();
+		node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
+		assertEquals( "diff-node-name", node.getName() );
+		assertEquals( 1, node.getVersion() );
+		s.delete( node );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testAddNewChildToReadOnlyParent() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode parent = new VersionedNode( "parent", "parent" );
+		s.persist( parent );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		s = openSession();
+		s.beginTransaction();
+		VersionedNode parentManaged = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		s.setReadOnly( parentManaged, true );
+		parentManaged.setName( "new parent name" );
+		VersionedNode child = new VersionedNode( "child", "child");
+		parentManaged.addChild( child );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 0 );
+
+		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() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertNull( child );
+		s.delete( parent );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testUpdateParentWithNewChildCommitWithReadOnlyParent() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode parent = new VersionedNode( "parent", "parent" );
+		s.persist( parent );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		parent.setName( "new parent name" );
+		VersionedNode child = new VersionedNode( "child", "child");
+		parent.addChild( child );
+
+		s = openSession();
+		s.beginTransaction();
+		s.update( parent );
+		s.setReadOnly( parent, true );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 1 );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( parent.getName(), "parent" );
+		assertEquals( 1, parent.getChildren().size() );
+		assertEquals( 0, parent.getVersion() );
+		assertSame( parent, child.getParent() );
+		assertSame( child, parent.getChildren().iterator().next() );
+		assertEquals( 0, child.getVersion() );
+		s.delete( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testMergeDetachedParentWithNewChildCommitWithReadOnlyParent() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode parent = new VersionedNode( "parent", "parent" );
+		s.persist( parent );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		parent.setName( "new parent name" );
+		VersionedNode child = new VersionedNode( "child", "child");
+		parent.addChild( child );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.merge( parent );
+		s.setReadOnly( parent, true );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 1 );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( parent.getName(), "parent" );
+		assertEquals( 1, parent.getChildren().size() );
+		assertEquals( 0, parent.getVersion() );
+		assertSame( parent, child.getParent() );
+		assertSame( child, parent.getChildren().iterator().next() );
+		assertEquals( 0, child.getVersion() );
+		s.delete( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testGetParentMakeReadOnlyThenMergeDetachedParentWithNewChildC() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode parent = new VersionedNode( "parent", "parent" );
+		s.persist( parent );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		parent.setName( "new parent name" );
+		VersionedNode child = new VersionedNode( "child", "child");
+		parent.addChild( child );
+
+		s = openSession();
+		s.beginTransaction();
+		VersionedNode parentManaged = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		s.setReadOnly( parentManaged, true );
+		VersionedNode parentMerged = ( VersionedNode ) s.merge( parent );
+		assertSame( parentManaged, parentMerged );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 1 );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( parent.getName(), "parent" );
+		assertEquals( 1, parent.getChildren().size() );
+		assertEquals( 0, parent.getVersion() );
+		assertSame( parent, child.getParent() );
+		assertSame( child, parent.getChildren().iterator().next() );
+		assertEquals( 0, child.getVersion() );
+		s.delete( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+
+	public void testAddNewParentToReadOnlyChild() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode child = new VersionedNode( "child", "child" );
+		s.persist( child );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		s = openSession();
+		s.beginTransaction();
+		VersionedNode childManaged = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		s.setReadOnly( childManaged, true );
+		childManaged.setName( "new child name" );
+		VersionedNode parent = new VersionedNode( "parent", "parent");
+		parent.addChild( childManaged );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 0 );
+
+		s = openSession();
+		s.beginTransaction();
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( "child", child.getName() );
+		assertNull( child.getParent() );
+		assertEquals( 0, child.getVersion() );
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		assertNull( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testUpdateChildWithNewParentCommitWithReadOnlyChild() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode child = new VersionedNode( "child", "child" );
+		s.persist( child );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		child.setName( "new child name" );
+		VersionedNode parent = new VersionedNode( "parent", "parent");
+		parent.addChild( child );
+
+		s = openSession();
+		s.beginTransaction();
+		s.update( child );
+		s.setReadOnly( child, true );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 0 );
+		assertInsertCount( 1 );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( child.getName(), "child" );
+		assertNull( child.getParent() );
+		assertEquals( 0, child.getVersion() );
+		assertNotNull( parent );
+		assertEquals( 0, parent.getChildren().size() );
+		assertEquals( 0, parent.getVersion() );
+		s.delete( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testMergeDetachedChildWithNewParentCommitWithReadOnlyChild() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode child = new VersionedNode( "child", "child" );
+		s.persist( child );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		child.setName( "new child name" );
+		VersionedNode parent = new VersionedNode( "parent", "parent");
+		parent.addChild( child );
+
+		s = openSession();
+		s.beginTransaction();
+		child = ( VersionedNode ) s.merge( child );
+		s.setReadOnly( child, true );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 1 );
+		assertInsertCount( 1 );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( child.getName(), "child" );
+		assertNull( child.getParent() );
+		assertEquals( 0, child.getVersion() );
+		assertNotNull( parent );
+		assertEquals( 0, parent.getChildren().size() );
+		assertEquals( 1, parent.getVersion() );	// hmmm, why is was version updated?
+		s.delete( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testGetChildMakeReadOnlyThenMergeDetachedChildWithNewParent() throws Exception {
+		Session s = openSession();
+		s.beginTransaction();
+		VersionedNode child = new VersionedNode( "child", "child" );
+		s.persist( child );
+		s.getTransaction().commit();
+		s.close();
+
+		clearCounts();
+
+		child.setName( "new child name" );
+		VersionedNode parent = new VersionedNode( "parent", "parent");
+		parent.addChild( child );
+
+		s = openSession();
+		s.beginTransaction();
+		VersionedNode childManaged = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		s.setReadOnly( childManaged, true );
+		VersionedNode childMerged = ( VersionedNode ) s.merge( child );
+		assertSame( childManaged, childMerged );
+		s.getTransaction().commit();
+		s.close();
+
+		assertUpdateCount( 1 );
+		assertInsertCount( 1 );
+
+		s = openSession();
+		s.beginTransaction();
+		parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
+		child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
+		assertEquals( child.getName(), "child" );
+		assertNull( child.getParent() );
+		assertEquals( 0, child.getVersion() );
+		assertNotNull( parent );
+		assertEquals( 0, parent.getChildren().size() );
+		assertEquals( 1, parent.getVersion() ); // / hmmm, why is was version updated?
+		s.delete( parent );
+		s.delete( child );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	protected void cleanupTest() throws Exception {
+		cleanup();
+		super.cleanupTest();
+	}
+
+	private void cleanup() {
+		Session s = sfi().openSession();
+		s.beginTransaction();
+
+		s.createQuery( "delete from VersionedNode where parent is not null" ).executeUpdate();
+		s.createQuery( "delete from VersionedNode" ).executeUpdate();
+
+		s.getTransaction().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 );
+	}
+}

Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.hbm.xml
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.hbm.xml	                        (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.hbm.xml	2009-05-06 01:18:43 UTC (rev 16512)
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.test.readonly">
+
+	<class name="VersionedNode" table="V_NODE">
+		<id name="id" column="ID" type="string">
+			<generator class="assigned"/>
+		</id>
+        <version name="version" column="VERS" type="long" />
+        <property name="name" column="NAME" type="string" />
+        <many-to-one name="parent" class="VersionedNode" cascade="persist,merge,save-update,evict,delete"/>
+        <set name="children"
+			inverse="true"
+			cascade="persist,merge,save-update,evict,delete">
+			<key column="parent"/>
+			<one-to-many class="VersionedNode"/>
+		</set>
+    </class>
+
+</hibernate-mapping>
+

Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.java	                        (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/readonly/VersionedNode.java	2009-05-06 01:18:43 UTC (rev 16512)
@@ -0,0 +1,96 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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.readonly;
+
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * VersionedNode
+ *
+ * @author Gail Badner
+ */
+public class VersionedNode {
+	private String id;
+	private String name;
+	private long version;
+
+	private VersionedNode parent;
+	private Set children = new HashSet();
+
+	public VersionedNode() {
+	}
+
+	public VersionedNode(String id, String name) {
+		this.id = id;
+		this.name = name;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public long getVersion() {
+		return version;
+	}
+
+	public void setVersion(long version) {
+		this.version = version;
+	}
+
+	public VersionedNode getParent() {
+		return parent;
+	}
+
+	public void setParent(VersionedNode parent) {
+		this.parent = parent;
+	}
+
+	public Set getChildren() {
+		return children;
+	}
+
+	public void setChildren(Set children) {
+		this.children = children;
+	}
+
+	public void addChild(VersionedNode child) {
+		child.setParent( this );
+		children.add( child );
+	}
+}




More information about the hibernate-commits mailing list