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:
parent
746fcef83a
commit
53c075ed0c
|
@ -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 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener
|
|||
// 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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,6 +188,7 @@ import org.hibernate.test.propertyref.inheritence.union.UnionSubclassPropertyRef
|
|||
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 @@ public class AllTests {
|
|||
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 @@ public class AllTests {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,11 @@ public class ImmutableTest extends FunctionalTestCase {
|
|||
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
|
||||
assertEquals( c.getCustomerName(), "gavin" );
|
||||
assertEquals( c.getVariations().size(), 2 );
|
||||
cv1 = (ContractVariation) c.getVariations().iterator().next();
|
||||
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 +92,238 @@ public class ImmutableTest extends FunctionalTestCase {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue