HHH-3662 : Merging read-only entities causes AssertionError

git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_2@16513 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Gail Badner 2009-05-06 01:34:24 +00:00
parent 746fcef83a
commit 53c075ed0c
7 changed files with 952 additions and 5 deletions

View File

@ -1,4 +1,28 @@
//$Id$ //$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; package org.hibernate.event.def;
import java.io.Serializable; import java.io.Serializable;
@ -70,8 +94,8 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener
// TODO: cache the entity name somewhere so that it is available to this exception // TODO: cache the entity name somewhere so that it is available to this exception
// entity name will not be available for non-POJO entities // entity name will not be available for non-POJO entities
} }
if ( entry.getStatus() != Status.MANAGED ) { if ( entry.getStatus() != Status.MANAGED && entry.getStatus() != Status.READ_ONLY ) {
throw new AssertionFailure( "Merged entity does not have status set to MANAGED; "+entry+" status="+entry.getStatus() ); throw new AssertionFailure( "Merged entity does not have status set to MANAGED or READ_ONLY; "+entry+" status="+entry.getStatus() );
} }
} }
} }

View File

@ -188,6 +188,7 @@ import org.hibernate.test.propertyref.inheritence.union.UnionSubclassPropertyRef
import org.hibernate.test.proxy.ProxyTest; import org.hibernate.test.proxy.ProxyTest;
import org.hibernate.test.querycache.QueryCacheTest; import org.hibernate.test.querycache.QueryCacheTest;
import org.hibernate.test.readonly.ReadOnlyTest; import org.hibernate.test.readonly.ReadOnlyTest;
import org.hibernate.test.readonly.ReadOnlyVersionedNodesTest;
import org.hibernate.test.reattachment.CollectionReattachmentTest; import org.hibernate.test.reattachment.CollectionReattachmentTest;
import org.hibernate.test.reattachment.ProxyReattachmentTest; import org.hibernate.test.reattachment.ProxyReattachmentTest;
import org.hibernate.test.rowid.RowIdTest; import org.hibernate.test.rowid.RowIdTest;
@ -304,6 +305,7 @@ public class AllTests {
suite.addTest( EmbeddedCompositeIdTest.suite() ); suite.addTest( EmbeddedCompositeIdTest.suite() );
suite.addTest( ImmutableTest.suite() ); suite.addTest( ImmutableTest.suite() );
suite.addTest( ReadOnlyTest.suite() ); suite.addTest( ReadOnlyTest.suite() );
suite.addTest( ReadOnlyVersionedNodesTest.suite() );
suite.addTest( IdClassTest.suite() ); suite.addTest( IdClassTest.suite() );
suite.addTest( ArrayTest.suite() ); suite.addTest( ArrayTest.suite() );
suite.addTest( TernaryTest.suite() ); suite.addTest( TernaryTest.suite() );

View File

@ -1,10 +1,37 @@
//$Id$ //$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; package org.hibernate.test.immutable;
import java.util.Iterator;
import junit.framework.Test; import junit.framework.Test;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Projections; import org.hibernate.criterion.Projections;
import org.hibernate.junit.functional.FunctionalTestCase; import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite; import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
@ -53,8 +80,11 @@ public class ImmutableTest extends FunctionalTestCase {
c = (Contract) s.createCriteria(Contract.class).uniqueResult(); c = (Contract) s.createCriteria(Contract.class).uniqueResult();
assertEquals( c.getCustomerName(), "gavin" ); assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 ); assertEquals( c.getVariations().size(), 2 );
cv1 = (ContractVariation) c.getVariations().iterator().next(); Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
assertEquals( cv1.getText(), "expensive" ); assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
s.delete(c); s.delete(c);
assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) ); assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) ); assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Integer(0) );
@ -62,5 +92,238 @@ public class ImmutableTest extends FunctionalTestCase {
s.close(); 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) );
t.commit();
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();
}
}

View File

@ -1,4 +1,28 @@
//$Id$ //$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; package org.hibernate.test.readonly;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -117,5 +141,38 @@ public class ReadOnlyTest extends FunctionalTestCase {
} }
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();
}
} }

View File

@ -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 );
}
}

View File

@ -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>

View File

@ -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 );
}
}