Author: gbadner
Date: 2009-05-05 21:34:24 -0400 (Tue, 05 May 2009)
New Revision: 16513
Added:
core/branches/Branch_3_2/test/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
core/branches/Branch_3_2/test/org/hibernate/test/readonly/VersionedNode.hbm.xml
core/branches/Branch_3_2/test/org/hibernate/test/readonly/VersionedNode.java
Modified:
core/branches/Branch_3_2/src/org/hibernate/event/def/DefaultMergeEventListener.java
core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java
core/branches/Branch_3_2/test/org/hibernate/test/immutable/ImmutableTest.java
core/branches/Branch_3_2/test/org/hibernate/test/readonly/ReadOnlyTest.java
Log:
HHH-3662 : Merging read-only entities causes AssertionError
Modified:
core/branches/Branch_3_2/src/org/hibernate/event/def/DefaultMergeEventListener.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/event/def/DefaultMergeEventListener.java 2009-05-06
01:18:43 UTC (rev 16512)
+++
core/branches/Branch_3_2/src/org/hibernate/event/def/DefaultMergeEventListener.java 2009-05-06
01:34:24 UTC (rev 16513)
@@ -1,4 +1,28 @@
//$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.event.def;
import java.io.Serializable;
@@ -70,8 +94,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_2/test/org/hibernate/test/AllTests.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java 2009-05-06 01:18:43 UTC
(rev 16512)
+++ core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java 2009-05-06 01:34:24 UTC
(rev 16513)
@@ -188,6 +188,7 @@
import org.hibernate.test.proxy.ProxyTest;
import org.hibernate.test.querycache.QueryCacheTest;
import org.hibernate.test.readonly.ReadOnlyTest;
+import org.hibernate.test.readonly.ReadOnlyVersionedNodesTest;
import org.hibernate.test.reattachment.CollectionReattachmentTest;
import org.hibernate.test.reattachment.ProxyReattachmentTest;
import org.hibernate.test.rowid.RowIdTest;
@@ -304,6 +305,7 @@
suite.addTest( EmbeddedCompositeIdTest.suite() );
suite.addTest( ImmutableTest.suite() );
suite.addTest( ReadOnlyTest.suite() );
+ suite.addTest( ReadOnlyVersionedNodesTest.suite() );
suite.addTest( IdClassTest.suite() );
suite.addTest( ArrayTest.suite() );
suite.addTest( TernaryTest.suite() );
@@ -633,4 +635,4 @@
}
}
}
-}
\ No newline at end of file
+}
Modified: core/branches/Branch_3_2/test/org/hibernate/test/immutable/ImmutableTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/immutable/ImmutableTest.java 2009-05-06
01:18:43 UTC (rev 16512)
+++
core/branches/Branch_3_2/test/org/hibernate/test/immutable/ImmutableTest.java 2009-05-06
01:34:24 UTC (rev 16513)
@@ -1,10 +1,37 @@
//$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.immutable;
+import java.util.Iterator;
+
import junit.framework.Test;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.HibernateException;
import org.hibernate.criterion.Projections;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
@@ -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,165 @@
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_2/test/org/hibernate/test/readonly/ReadOnlyTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/readonly/ReadOnlyTest.java 2009-05-06
01:18:43 UTC (rev 16512)
+++ core/branches/Branch_3_2/test/org/hibernate/test/readonly/ReadOnlyTest.java 2009-05-06
01:34:24 UTC (rev 16513)
@@ -1,4 +1,28 @@
//$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.math.BigDecimal;
@@ -117,5 +141,38 @@
}
+ 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_2/test/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/readonly/ReadOnlyVersionedNodesTest.java 2009-05-06
01:34:24 UTC (rev 16513)
@@ -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_2/test/org/hibernate/test/readonly/VersionedNode.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/readonly/VersionedNode.hbm.xml
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/readonly/VersionedNode.hbm.xml 2009-05-06
01:34:24 UTC (rev 16513)
@@ -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_2/test/org/hibernate/test/readonly/VersionedNode.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/readonly/VersionedNode.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/readonly/VersionedNode.java 2009-05-06
01:34:24 UTC (rev 16513)
@@ -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 );
+ }
+}