Fix refresh of a Proxy instance

This commit is contained in:
Andrea Boriero 2021-11-26 16:14:36 +01:00 committed by Andrea Boriero
parent 1589686608
commit 0fbfc30eaa
10 changed files with 2169 additions and 2128 deletions

View File

@ -590,9 +590,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
final PersistenceContext persistenceContext = session.getPersistenceContext();
if ( entityInstance instanceof HibernateProxy ) {
LazyInitializer hibernateLazyInitializer = ( (HibernateProxy) entityInstance ).getHibernateLazyInitializer();
if ( !hibernateLazyInitializer.isUninitialized() ) {
return;
}
Object instance = persistenceContext.getEntity( entityKey );
if ( instance == null ) {

View File

@ -127,26 +127,6 @@ public class StandardRowReader<T> implements RowReader<T> {
// todo (6.0) : we may want to split handling of initializers into specific sub-type handling
// - meaning we'd have something like:
// for ( EntityInitializer initializer : entityInitializers ) {
// initializer.resolveKey( rowProcessingState );
// }
//
// for ( EntityInitializer initializer : collectionInitializers ) {
// initializer.resolveKey( rowProcessingState );
// }
//
// for ( Initializer initializer : entityInitializers ) {
// initializer.resolveInstance( rowProcessingState );
// }
//
// for ( EntityInitializer initializer : collectionInitializers ) {
// initializer.resolveInstance( rowProcessingState );
// }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// old
final int numberOfInitializers = initializers.size();
for ( int i = 0; i < numberOfInitializers; i++ ) {

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.readonly;
package org.hibernate.orm.test.readonly;
import java.math.BigDecimal;
import java.util.Arrays;
@ -18,14 +18,21 @@ import org.hibernate.Transaction;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.proxy.HibernateProxy;
import org.junit.Test;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.test.readonly.Container;
import org.hibernate.test.readonly.DataPoint;
import org.hibernate.test.readonly.Info;
import org.hibernate.test.readonly.Owner;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Model:
@ -48,15 +55,14 @@ import static org.junit.Assert.assertTrue;
*
* @author Gail Badner
*/
@DomainModel(
xmlMappings = { "org/hibernate/test/readonly/DataPoint.hbm.xml" }
)
public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@Override
public String[] getMappings() {
return new String[] { "readonly/DataPoint.hbm.xml" };
}
@Test
@SuppressWarnings( {"unchecked"})
public void testExistingModifiableAfterSetSessionReadOnly() {
public void testExistingModifiableAfterSetSessionReadOnly(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -74,7 +80,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -97,7 +103,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
assertSame( cOrig, c );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
s.evict( cOrig );
c = ( Container ) s.get( Container.class, cOrig.getId() );
c = s.get( Container.class, cOrig.getId() );
assertNotSame( cOrig, c );
expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -140,7 +146,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -153,7 +159,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@Test
@SuppressWarnings( {"unchecked"})
public void testExistingReadOnlyAfterSetSessionModifiable() {
public void testExistingReadOnlyAfterSetSessionModifiable(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
@ -171,7 +177,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
)
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -182,7 +188,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
Container c = ( Container ) s.get( Container.class, cOrig.getId() );
@ -230,7 +236,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -243,7 +249,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@Test
@SuppressWarnings( {"unchecked"})
public void testExistingReadOnlyAfterSetSessionModifiableExisting() {
public void testExistingReadOnlyAfterSetSessionModifiableExisting(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -261,7 +267,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -272,7 +278,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
Container c = ( Container ) s.get( Container.class, cOrig.getId() );
@ -321,7 +327,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -334,7 +340,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testExistingReadOnlyAfterSetSessionModifiableExistingEntityReadOnly() {
public void testExistingReadOnlyAfterSetSessionModifiableExistingEntityReadOnly(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -352,7 +358,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -363,7 +369,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
Container c = ( Container ) s.get( Container.class, cOrig.getId() );
@ -415,7 +421,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -428,7 +434,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testExistingReadOnlyAfterSetSessionModifiableProxyExisting() {
public void testExistingReadOnlyAfterSetSessionModifiableProxyExisting(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -446,7 +452,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -457,7 +463,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
Container c = ( Container ) s.get( Container.class, cOrig.getId() );
@ -506,7 +512,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -519,7 +525,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testExistingReadOnlyAfterSetSessionModifiableExistingProxyReadOnly() {
public void testExistingReadOnlyAfterSetSessionModifiableExistingProxyReadOnly(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -537,7 +543,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
DataPoint lazyDataPointOrig = ( DataPoint ) cOrig.getLazyDataPoints().iterator().next();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -548,7 +554,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
Container c = ( Container ) s.get( Container.class, cOrig.getId() );
@ -600,7 +606,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -612,7 +618,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testDefaultModifiableWithReadOnlyQueryForEntity() {
public void testDefaultModifiableWithReadOnlyQueryForEntity(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -630,7 +636,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -641,7 +647,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
assertFalse( s.isDefaultReadOnly() );
Container c = ( Container ) s.createQuery( "from Container where id=" + cOrig.getId() )
@ -687,7 +693,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -699,7 +705,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testDefaultReadOnlyWithModifiableQueryForEntity() {
public void testDefaultReadOnlyWithModifiableQueryForEntity(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -717,7 +723,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -728,7 +734,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
assertTrue( s.isDefaultReadOnly() );
@ -762,7 +768,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -774,7 +780,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testDefaultReadOnlyWithQueryForEntity() {
public void testDefaultReadOnlyWithQueryForEntity(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -792,7 +798,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -803,7 +809,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
assertTrue( s.isDefaultReadOnly() );
@ -850,7 +856,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -862,7 +868,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testDefaultModifiableWithQueryForEntity() {
public void testDefaultModifiableWithQueryForEntity(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -880,7 +886,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -891,7 +897,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
assertFalse( s.isDefaultReadOnly() );
Container c = ( Container ) s.createQuery( "from Container where id=" + cOrig.getId() )
@ -924,7 +930,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
checkContainer( c, expectedInitializedObjects, expectedReadOnlyObjects, s );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -936,7 +942,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
@SuppressWarnings( {"unchecked"})
@Test
public void testDefaultModifiableWithReadOnlyQueryForCollectionEntities() {
public void testDefaultModifiableWithReadOnlyQueryForCollectionEntities(SessionFactoryScope scope) {
Container cOrig = createContainer();
Set expectedInitializedObjects = new HashSet(
Arrays.asList(
@ -954,7 +960,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
);
Set expectedReadOnlyObjects = new HashSet();
Session s = openSession();
Session s = openSession(scope);
assertFalse( s.isDefaultReadOnly() );
Transaction t = s.beginTransaction();
s.save( cOrig );
@ -965,7 +971,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
assertFalse( s.isDefaultReadOnly() );
DataPoint dp = ( DataPoint ) s.createQuery( "select c.lazyDataPoints from Container c join c.lazyDataPoints where c.id=" + cOrig.getId() )
@ -973,7 +979,7 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
assertTrue( s.isReadOnly( dp ) );
t.commit();
s.close();
s = openSession();
s = openSession(scope);
t = s.beginTransaction();
s.createQuery("delete from DataPoint").executeUpdate();
s.createQuery("delete from Container").executeUpdate();
@ -1037,4 +1043,8 @@ public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {
}
}
private Session openSession(SessionFactoryScope scope) {
return scope.getSessionFactory().openSession();
}
}

View File

@ -0,0 +1,658 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.readonly;
import java.math.BigDecimal;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.test.readonly.DataPoint;
import org.hibernate.test.readonly.TextHolder;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
* @author Gail Badner
*/
@DomainModel(
xmlMappings = {
"org/hibernate/test/readonly/DataPoint.hbm.xml",
"org/hibernate/test/readonly/TextHolder.hbm.xml"
}
)
public class ReadOnlyTest extends AbstractReadOnlyTest {
@Test
public void testReadOnlyOnProxies(SessionFactoryScope scope) {
clearCounts( scope );
long dpId = scope.fromTransaction(
session -> {
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
) );
dp.setDescription( "original" );
session.save( dp );
return dp.getId();
}
);
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
DataPoint dp = session.load( DataPoint.class, new Long( dpId ) );
assertFalse( Hibernate.isInitialized( dp ), "was initialized" );
session.setReadOnly( dp, true );
assertFalse( Hibernate.isInitialized( dp ), "was initialized during setReadOnly" );
dp.setDescription( "changed" );
assertTrue( Hibernate.isInitialized( dp ), "was not initialized during mod" );
assertEquals( "changed", dp.getDescription(), "desc not changed in memory" );
session.flush();
}
);
assertUpdateCount( 0, scope );
scope.inTransaction(
session -> {
List list = session.createQuery( "from DataPoint where description = 'changed'" ).list();
assertEquals( 0, list.size(), "change written to database" );
assertEquals( 1, session.createQuery( "delete from DataPoint" ).executeUpdate() );
}
);
assertUpdateCount( 0, scope );
//deletes from Query.executeUpdate() are not tracked
//assertDeleteCount( 1 );
}
@Test
public void testReadOnlyMode(SessionFactoryScope scope) {
clearCounts( scope );
scope.inTransaction(
session -> {
for ( int i = 0; i < 100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal( i * 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(
19,
BigDecimal.ROUND_DOWN
) );
session.save( dp );
}
}
);
assertInsertCount( 100, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
scope.inSession(
session -> {
try {
session.getTransaction().begin();
int i = 0;
ScrollableResults sr = session.createQuery( "from DataPoint dp order by dp.x asc" )
.setReadOnly( true )
.scroll( ScrollMode.FORWARD_ONLY );
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get();
if ( ++i == 50 ) {
session.setReadOnly( dp, false );
}
dp.setDescription( "done!" );
}
session.getTransaction().commit();
assertUpdateCount( 1, scope );
clearCounts( scope );
session.clear();
session.getTransaction().begin();
List single = session.createQuery( "from DataPoint where description='done!'" ).list();
assertEquals( single.size(), 1 );
assertEquals( 100, session.createQuery( "delete from DataPoint" ).executeUpdate() );
session.getTransaction().commit();
}
finally {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
}
}
);
assertUpdateCount( 0, scope );
//deletes from Query.executeUpdate() are not tracked
//assertDeleteCount( 100 );
}
@Test
public void testReadOnlyModeAutoFlushOnQuery(SessionFactoryScope scope) {
clearCounts( scope );
scope.inTransaction(
session -> {
DataPoint dpFirst = null;
for ( int i = 0; i < 100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal( i * 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(
19,
BigDecimal.ROUND_DOWN
) );
session.save( dp );
}
assertInsertCount( 0, scope );
assertUpdateCount( 0, scope );
ScrollableResults sr = session.createQuery( "from DataPoint dp order by dp.x asc" )
.setReadOnly( true )
.scroll( ScrollMode.FORWARD_ONLY );
assertInsertCount( 100, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get();
assertFalse( session.isReadOnly( dp ) );
session.delete( dp );
}
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 100, scope );
}
@Test
public void testSaveReadOnlyModifyInSaveTransaction(SessionFactoryScope scope) {
clearCounts( scope );
DataPoint d = new DataPoint();
scope.inTransaction(
session -> {
d.setDescription( "original" );
d.setX( new BigDecimal( 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) );
d.setY( new BigDecimal( Math.cos( d.getX().doubleValue() ) ).setScale(
19,
BigDecimal.ROUND_DOWN
) );
session.save( d );
session.setReadOnly( d, true );
d.setDescription( "different" );
}
);
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
scope.inSession(
session -> {
try {
session.beginTransaction();
DataPoint dp = session.get( DataPoint.class, d.getId() );
session.setReadOnly( dp, true );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
session.refresh( dp );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
session.getTransaction().commit();
assertInsertCount( 0, scope );
assertUpdateCount( 0, scope );
session.clear();
session.beginTransaction();
dp = session.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
session.delete( dp );
session.getTransaction().commit();
}
finally {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
}
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
clearCounts( scope );
}
@Test
public void testReadOnlyRefresh(SessionFactoryScope scope) {
clearCounts( scope );
DataPoint d = new DataPoint();
scope.inTransaction(
session -> {
d.setDescription( "original" );
d.setX( new BigDecimal( 0.1d ).setScale( 19, BigDecimal.ROUND_DOWN ) );
d.setY( new BigDecimal( Math.cos( d.getX().doubleValue() ) ).setScale(
19,
BigDecimal.ROUND_DOWN
) );
session.save( d );
}
);
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
scope.inSession(
session -> {
try {
session.beginTransaction();
DataPoint dp = session.get( DataPoint.class, d.getId() );
session.setReadOnly( dp, true );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
session.refresh( dp );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
session.getTransaction().commit();
assertInsertCount( 0, scope );
assertUpdateCount( 0, scope );
session.clear();
session.beginTransaction();
dp = session.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
session.delete( dp );
session.getTransaction().commit();
}
finally {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
}
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
clearCounts( scope );
}
@Test
public void testReadOnlyRefreshDetached(SessionFactoryScope scope) {
clearCounts( scope );
Session s = openSession( scope );
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription( "original" );
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();
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
s = openSession( scope );
t = s.beginTransaction();
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
s.setReadOnly( dp, true );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
t.commit();
assertInsertCount( 0, scope );
assertUpdateCount( 0, scope );
s.clear();
t = s.beginTransaction();
dp = (DataPoint) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
@Test
public void testReadOnlyDelete(SessionFactoryScope scope) {
clearCounts( scope );
Session s = openSession( scope );
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();
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
s = openSession( scope );
t = s.beginTransaction();
dp = (DataPoint) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
s = openSession( scope );
t = s.beginTransaction();
List list = s.createQuery( "from DataPoint where description='done!'" ).list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
@Test
public void testReadOnlyGetModifyAndDelete(SessionFactoryScope scope) {
clearCounts( scope );
Session s = openSession( scope );
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();
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
s = openSession( scope );
t = s.beginTransaction();
dp = (DataPoint) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
dp.setDescription( "a DataPoint" );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
clearCounts( scope );
s = openSession( scope );
t = s.beginTransaction();
List list = s.createQuery( "from DataPoint where description='done!'" ).list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
@Test
public void testReadOnlyModeWithExistingModifiableEntity(SessionFactoryScope scope) {
clearCounts( scope );
Session s = openSession( scope );
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i = 0; i < 100; i++ ) {
dp = new DataPoint();
dp.setX( new BigDecimal( i * 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();
assertInsertCount( 100, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
s = openSession( scope );
t = s.beginTransaction();
DataPoint dpLast = (DataPoint) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
int i = 0;
ScrollableResults sr = s.createQuery( "from DataPoint dp order by dp.x asc" )
.setReadOnly( true )
.scroll( ScrollMode.FORWARD_ONLY );
int nExpectedChanges = 0;
while ( sr.next() ) {
dp = (DataPoint) sr.get();
if ( dp.getId() == dpLast.getId() ) {
//dpLast existed in the session before executing the read-only query
assertFalse( s.isReadOnly( dp ) );
}
else {
assertTrue( s.isReadOnly( dp ) );
}
if ( ++i == 50 ) {
s.setReadOnly( dp, false );
nExpectedChanges = ( dp == dpLast ? 1 : 2 );
}
dp.setDescription( "done!" );
}
t.commit();
s.clear();
assertInsertCount( 0, scope );
assertUpdateCount( nExpectedChanges, scope );
clearCounts( scope );
t = s.beginTransaction();
List list = s.createQuery( "from DataPoint where description='done!'" ).list();
assertEquals( list.size(), nExpectedChanges );
assertEquals( 100, s.createQuery( "delete from DataPoint" ).executeUpdate() );
t.commit();
s.close();
assertUpdateCount( 0, scope );
}
@Test
public void testModifiableModeWithExistingReadOnlyEntity(SessionFactoryScope scope) {
clearCounts( scope );
Session s = openSession( scope );
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i = 0; i < 100; i++ ) {
dp = new DataPoint();
dp.setX( new BigDecimal( i * 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();
assertInsertCount( 100, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
s = openSession( scope );
t = s.beginTransaction();
DataPoint dpLast = (DataPoint) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
s.setReadOnly( dpLast, true );
assertTrue( s.isReadOnly( dpLast ) );
dpLast.setDescription( "oy" );
int i = 0;
assertUpdateCount( 0, scope );
ScrollableResults sr = s.createQuery( "from DataPoint dp order by dp.x asc" )
.setReadOnly( false )
.scroll( ScrollMode.FORWARD_ONLY );
int nExpectedChanges = 0;
while ( sr.next() ) {
dp = (DataPoint) sr.get();
if ( dp.getId() == dpLast.getId() ) {
//dpLast existed in the session before executing the read-only query
assertTrue( s.isReadOnly( dp ) );
}
else {
assertFalse( s.isReadOnly( dp ) );
}
if ( ++i == 50 ) {
s.setReadOnly( dp, true );
nExpectedChanges = ( dp == dpLast ? 99 : 98 );
}
dp.setDescription( "done!" );
}
t.commit();
s.clear();
assertUpdateCount( nExpectedChanges, scope );
clearCounts( scope );
t = s.beginTransaction();
List list = s.createQuery( "from DataPoint where description='done!'" ).list();
assertEquals( list.size(), nExpectedChanges );
assertEquals( 100, s.createQuery( "delete from DataPoint" ).executeUpdate() );
t.commit();
s.close();
assertUpdateCount( 0, scope );
}
@Test
public void testReadOnlyOnTextType(SessionFactoryScope scope) {
final String origText = "some huge text string";
final String newText = "some even bigger text string";
clearCounts( scope );
Session s = openSession( scope );
s.beginTransaction();
TextHolder holder = new TextHolder( origText );
s.save( holder );
Long id = holder.getId();
s.getTransaction().commit();
s.close();
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
s = openSession( scope );
s.beginTransaction();
holder = (TextHolder) s.get( TextHolder.class, id );
s.setReadOnly( holder, true );
holder.setTheText( newText );
s.flush();
s.getTransaction().commit();
s.close();
assertUpdateCount( 0, scope );
s = openSession( scope );
s.beginTransaction();
holder = (TextHolder) s.get( TextHolder.class, id );
assertEquals( origText, holder.getTheText(), "change written to database" );
s.delete( holder );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
@Test
public void testMergeWithReadOnlyEntity(SessionFactoryScope scope) {
clearCounts( scope );
Session s = openSession( scope );
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();
assertInsertCount( 1, scope );
assertUpdateCount( 0, scope );
clearCounts( scope );
dp.setDescription( "description" );
s = openSession( scope );
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();
assertUpdateCount( 0, scope );
s = openSession( scope );
t = s.beginTransaction();
dpManaged = (DataPoint) s.get( DataPoint.class, new Long( dp.getId() ) );
assertNull( dpManaged.getDescription() );
s.delete( dpManaged );
t.commit();
s.close();
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
private Session openSession(SessionFactoryScope scope) {
return scope.getSessionFactory().openSession();
}
}

View File

@ -0,0 +1,658 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.readonly;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.test.readonly.VersionedNode;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* @author Gail Badner
*/
@DomainModel(
xmlMappings = "org/hibernate/test/readonly/VersionedNode.hbm.xml"
)
public class ReadOnlyVersionedNodesTest extends AbstractReadOnlyTest {
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "select v from VersionedNode v" ).list()
.forEach( node -> session.delete( node ) );
}
);
}
@Test
public void testSetReadOnlyTrueAndFalse(SessionFactoryScope scope) {
VersionedNode n = createVersionNode( scope );
clearCounts( scope );
scope.inSession(
session -> {
try {
session.beginTransaction();
VersionedNode node = session.get( VersionedNode.class, n.getId() );
session.setReadOnly( node, true );
node.setName( "node-name" );
session.getTransaction().commit();
assertUpdateCount( 0, scope );
assertInsertCount( 0, scope );
// the changed name is still in node
assertEquals( "node-name", node.getName() );
session.beginTransaction();
node = session.get( VersionedNode.class, node.getId() );
// the changed name is still in the session
assertEquals( "node-name", node.getName() );
session.refresh( node );
// after refresh, the name reverts to the original value
assertEquals( "node", node.getName() );
node = session.get( VersionedNode.class, node.getId() );
assertEquals( "node", node.getName() );
session.getTransaction().commit();
}
finally {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
}
}
);
assertUpdateCount( 0, scope );
assertInsertCount( 0, scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
assertEquals( "node", node.getName() );
session.setReadOnly( node, true );
node.setName( "diff-node-name" );
session.flush();
assertEquals( "diff-node-name", node.getName() );
session.refresh( node );
assertEquals( "node", node.getName() );
session.setReadOnly( node, false );
node.setName( "diff-node-name" );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 0, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
assertEquals( "diff-node-name", node.getName() );
assertEquals( 1, node.getVersion() );
session.setReadOnly( node, true );
session.delete( node );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
@Test
public void testUpdateSetReadOnlyTwice(SessionFactoryScope scope) {
VersionedNode n = createVersionNode( scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
node.setName( "node-name" );
session.setReadOnly( node, true );
session.setReadOnly( node, true );
}
);
assertUpdateCount( 0, scope );
assertInsertCount( 0, scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
assertEquals( "node", node.getName() );
assertEquals( 0, node.getVersion() );
session.setReadOnly( node, true );
session.delete( node );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
@Test
public void testUpdateSetModifiable(SessionFactoryScope scope) {
VersionedNode n = createVersionNode( scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
node.setName( "node-name" );
session.setReadOnly( node, false );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 0, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
session.setReadOnly( node, true );
session.delete( node );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
private VersionedNode createVersionNode(SessionFactoryScope scope) {
return scope.fromTransaction(
session -> {
VersionedNode nd = new VersionedNode( "node", "node" );
session.persist( nd );
return nd;
}
);
}
private VersionedNode createVersionNode(String id, String name, SessionFactoryScope scope) {
return scope.fromTransaction(
session -> {
VersionedNode nd = new VersionedNode( id, name );
session.persist( nd );
return nd;
}
);
}
@Test
@FailureExpected(jiraKey = "unknown")
public void testUpdateSetReadOnlySetModifiable(SessionFactoryScope scope) {
VersionedNode n = createVersionNode( scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
node.setName( "node-name" );
session.setReadOnly( node, true );
session.setReadOnly( node, false );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 0, scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
session.delete( node );
}
);
}
@Test
@FailureExpected(jiraKey = "unknown")
public void testSetReadOnlyUpdateSetModifiable(SessionFactoryScope scope) {
VersionedNode n = createVersionNode( scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
session.setReadOnly( node, true );
node.setName( "node-name" );
session.setReadOnly( node, false );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 0, scope );
scope.inTransaction(
session -> {
VersionedNode node = session.get( VersionedNode.class, n.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
session.delete( node );
}
);
}
@Test
public void testAddNewChildToReadOnlyParent(SessionFactoryScope scope) {
VersionedNode p = createVersionNode( "parent", "parent", scope );
clearCounts( scope );
VersionedNode c = scope.fromTransaction(
session -> {
VersionedNode parentManaged = session.get( VersionedNode.class, p.getId() );
session.setReadOnly( parentManaged, true );
parentManaged.setName( "new parent name" );
VersionedNode child = new VersionedNode( "child", "child" );
parentManaged.addChild( child );
return child;
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 1, scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
assertEquals( "parent", parent.getName() );
assertEquals( 1, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() );
VersionedNode child = session.get( VersionedNode.class, c.getId() );
assertNotNull( child );
session.delete( parent );
}
);
}
@Test
public void testUpdateParentWithNewChildCommitWithReadOnlyParent(SessionFactoryScope scope) {
VersionedNode p = createVersionNode( "parent", "parent", scope );
clearCounts( scope );
p.setName( "new parent name" );
VersionedNode c = new VersionedNode( "child", "child" );
p.addChild( c );
scope.inTransaction(
session -> {
session.update( p );
session.setReadOnly( p, true );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 1, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
VersionedNode child = session.get( VersionedNode.class, c.getId() );
assertEquals( parent.getName(), "parent" );
assertEquals( 1, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() );
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
session.setReadOnly( parent, true );
session.setReadOnly( child, true );
session.delete( parent );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
@Test
public void testMergeDetachedParentWithNewChildCommitWithReadOnlyParent(SessionFactoryScope scope) {
VersionedNode p = createVersionNode( "parent", "parent", scope );
clearCounts( scope );
p.setName( "new parent name" );
VersionedNode c = new VersionedNode( "child", "child" );
p.addChild( c );
scope.inTransaction(
session -> {
VersionedNode parent = (VersionedNode) session.merge( p );
session.setReadOnly( parent, true );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 1, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
VersionedNode child = session.get( VersionedNode.class, c.getId() );
assertEquals( parent.getName(), "parent" );
assertEquals( 1, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() );
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
session.setReadOnly( parent, true );
session.setReadOnly( child, true );
session.delete( parent );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
@Test
public void testGetParentMakeReadOnlyThenMergeDetachedParentWithNewChildC(SessionFactoryScope scope) {
VersionedNode p = createVersionNode( "parent", "parent", scope );
clearCounts( scope );
p.setName( "new parent name" );
VersionedNode c = new VersionedNode( "child", "child" );
p.addChild( c );
scope.inTransaction(
session -> {
VersionedNode parentManaged = session.get( VersionedNode.class, p.getId() );
session.setReadOnly( parentManaged, true );
VersionedNode parentMerged = (VersionedNode) session.merge( p );
assertSame( parentManaged, parentMerged );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 1, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
VersionedNode child = session.get( VersionedNode.class, c.getId() );
assertEquals( parent.getName(), "parent" );
assertEquals( 1, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() );
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
session.delete( parent );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
@Test
public void testMergeUnchangedDetachedParentChildren(SessionFactoryScope scope) {
VersionedNode p = new VersionedNode( "parent", "parent" );
VersionedNode c = new VersionedNode( "child", "child" );
scope.inTransaction(
session -> {
p.addChild( c );
session.persist( p );
}
);
clearCounts( scope );
VersionedNode parent = scope.fromTransaction(
session ->
(VersionedNode) session.merge( p )
);
assertUpdateCount( 0, scope );
assertInsertCount( 0, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parentGet = session.get( p.getClass(), p.getId() );
session.merge( parent );
}
);
assertUpdateCount( 0, scope );
assertInsertCount( 0, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parentLoad = (VersionedNode) session.load( parent.getClass(), parent.getId() );
session.merge( parent );
}
);
assertUpdateCount( 0, scope );
assertInsertCount( 0, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent_ = session.get( VersionedNode.class, parent.getId() );
VersionedNode child = session.get( VersionedNode.class, c.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() );
session.delete( parent_ );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
@Test
public void testAddNewParentToReadOnlyChild(SessionFactoryScope scope) {
VersionedNode c = createVersionNode( "child", "child", scope );
clearCounts( scope );
VersionedNode p = new VersionedNode( "parent", "parent" );
scope.inTransaction(
session -> {
VersionedNode childManaged = session.get( VersionedNode.class, c.getId() );
session.setReadOnly( childManaged, true );
childManaged.setName( "new child name" );
p.addChild( childManaged );
}
);
assertUpdateCount( 0, scope );
assertInsertCount( 1, scope );
scope.inTransaction(
session -> {
VersionedNode child = session.get( VersionedNode.class, c.getId() );
assertEquals( "child", child.getName() );
assertNull( child.getParent() );
assertEquals( 0, child.getVersion() );
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
assertNotNull( parent );
session.setReadOnly( child, true );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 1, scope );
}
@Test
public void testUpdateChildWithNewParentCommitWithReadOnlyChild(SessionFactoryScope scope) {
VersionedNode c = createVersionNode( "child", "child", scope );
clearCounts( scope );
c.setName( "new child name" );
VersionedNode p = new VersionedNode( "parent", "parent" );
p.addChild( c );
scope.inTransaction(
session -> {
session.update( c );
session.setReadOnly( c, true );
}
);
assertUpdateCount( 0, scope );
assertInsertCount( 1, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
VersionedNode child = session.get( VersionedNode.class, c.getId() );
assertEquals( child.getName(), "child" );
assertNull( child.getParent() );
assertEquals( 0, child.getVersion() );
assertNotNull( parent );
assertEquals( 0, parent.getChildren().size() );
assertEquals( 0, parent.getVersion() );
session.setReadOnly( parent, true );
session.setReadOnly( child, true );
session.delete( parent );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
@Test
public void testMergeDetachedChildWithNewParentCommitWithReadOnlyChild(SessionFactoryScope scope) {
VersionedNode c = createVersionNode( "child", "child", scope );
clearCounts( scope );
c.setName( "new child name" );
VersionedNode p = new VersionedNode( "parent", "parent" );
p.addChild( c );
scope.inTransaction(
session -> {
VersionedNode child = (VersionedNode) session.merge( c );
session.setReadOnly( child, true );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 1, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
VersionedNode child = session.get( VersionedNode.class, c.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?
session.setReadOnly( parent, true );
session.setReadOnly( child, true );
session.delete( parent );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
@Test
public void testGetChildMakeReadOnlyThenMergeDetachedChildWithNewParent(SessionFactoryScope scope) {
VersionedNode c = createVersionNode( "child", "child", scope );
clearCounts( scope );
c.setName( "new child name" );
VersionedNode p = new VersionedNode( "parent", "parent" );
p.addChild( c );
scope.inTransaction(
session -> {
VersionedNode childManaged = session.get( VersionedNode.class, c.getId() );
session.setReadOnly( childManaged, true );
VersionedNode childMerged = (VersionedNode) session.merge( c );
assertSame( childManaged, childMerged );
}
);
assertUpdateCount( 1, scope );
assertInsertCount( 1, scope );
clearCounts( scope );
scope.inTransaction(
session -> {
VersionedNode parent = session.get( VersionedNode.class, p.getId() );
VersionedNode child = session.get( VersionedNode.class, c.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?
session.setReadOnly( parent, true );
session.setReadOnly( child, true );
session.delete( parent );
session.delete( child );
}
);
assertUpdateCount( 0, scope );
assertDeleteCount( 2, scope );
}
protected void cleanupTest(SessionFactoryScope scope) throws Exception {
cleanup( scope );
}
private void cleanup(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from VersionedNode where parent is not null" ).executeUpdate();
session.createQuery( "delete from VersionedNode" ).executeUpdate();
}
);
}
}

View File

@ -7,50 +7,54 @@
package org.hibernate.test.readonly;
import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.hibernate.testing.orm.junit.SettingProvider;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.Assert.assertEquals;
/**
* @author Gail Badner
*/
public abstract class AbstractReadOnlyTest extends BaseCoreFunctionalTestCase {
@Override
public void configure(Configuration cfg) {
cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
@SessionFactory(
generateStatistics = true
)
@ServiceRegistry(
settings = @Setting(name = Environment.STATEMENT_BATCH_SIZE, value = "0"),
settingProviders = @SettingProvider(settingName = AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE, provider = AbstractReadOnlyTest.CacheModeProvider.class)
)
public abstract class AbstractReadOnlyTest {
public static class CacheModeProvider implements SettingProvider.Provider<CacheMode> {
@Override
public CacheMode getSetting() {
return CacheMode.IGNORE;
}
}
public Session openSession() {
Session s = super.openSession();
s.setCacheMode( getSessionCacheMode() );
return s;
protected void clearCounts(SessionFactoryScope scope) {
scope.getSessionFactory().getStatistics().clear();
}
protected CacheMode getSessionCacheMode() {
return CacheMode.IGNORE;
protected void assertInsertCount(int expected, SessionFactoryScope scope) {
int inserts = (int) scope.getSessionFactory().getStatistics().getEntityInsertCount();
assertEquals( expected, inserts, "unexpected insert count" );
}
protected void clearCounts() {
sessionFactory().getStatistics().clear();
protected void assertUpdateCount(int expected, SessionFactoryScope scope) {
int updates = (int) scope.getSessionFactory().getStatistics().getEntityUpdateCount();
assertEquals( expected, updates, "unexpected update counts" );
}
protected void assertInsertCount(int expected) {
int inserts = ( int ) sessionFactory().getStatistics().getEntityInsertCount();
assertEquals( "unexpected insert count", expected, inserts );
}
protected void assertUpdateCount(int expected) {
int updates = ( int ) sessionFactory().getStatistics().getEntityUpdateCount();
assertEquals( "unexpected update counts", expected, updates );
}
protected void assertDeleteCount(int expected) {
int deletes = ( int ) sessionFactory().getStatistics().getEntityDeleteCount();
assertEquals( "unexpected delete counts", expected, deletes );
protected void assertDeleteCount(int expected, SessionFactoryScope scope) {
int deletes = (int) scope.getSessionFactory().getStatistics().getEntityDeleteCount();
assertEquals( expected, deletes, "unexpected delete counts" );
}
}

View File

@ -1,603 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.readonly;
import java.math.BigDecimal;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
*
* @author Gavin King
* @author Gail Badner
*/
public class ReadOnlyTest extends AbstractReadOnlyTest {
@Override
public String[] getMappings() {
return new String[] { "readonly/DataPoint.hbm.xml", "readonly/TextHolder.hbm.xml" };
}
@Test
public void testReadOnlyOnProxies() {
clearCounts();
Session s = openSession();
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) );
dp.setDescription( "original" );
s.save( dp );
long dpId = dp.getId();
s.getTransaction().commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
s.beginTransaction();
dp = ( DataPoint ) s.load( DataPoint.class, new Long( dpId ) );
assertFalse( "was initialized", Hibernate.isInitialized( dp ) );
s.setReadOnly( dp, true );
assertFalse( "was initialized during setReadOnly", Hibernate.isInitialized( dp ) );
dp.setDescription( "changed" );
assertTrue( "was not initialized during mod", Hibernate.isInitialized( dp ) );
assertEquals( "desc not changed in memory", "changed", dp.getDescription() );
s.flush();
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
s = openSession();
s.beginTransaction();
List list = s.createQuery( "from DataPoint where description = 'changed'" ).list();
assertEquals( "change written to database", 0, list.size() );
assertEquals( 1, s.createQuery("delete from DataPoint").executeUpdate() );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
//deletes from Query.executeUpdate() are not tracked
//assertDeleteCount( 1 );
}
@Test
public void testReadOnlyMode() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
for ( int i=0; i<100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(i * 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();
assertInsertCount( 100 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(true)
.scroll(ScrollMode.FORWARD_ONLY);
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get();
if (++i==50) {
s.setReadOnly(dp, false);
}
dp.setDescription("done!");
}
t.commit();
assertUpdateCount( 1 );
clearCounts();
s.clear();
t = s.beginTransaction();
List single = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( single.size(), 1 );
assertEquals( 100, s.createQuery("delete from DataPoint").executeUpdate() );
t.commit();
s.close();
assertUpdateCount( 0 );
//deletes from Query.executeUpdate() are not tracked
//assertDeleteCount( 100 );
}
@Test
public void testReadOnlyModeAutoFlushOnQuery() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dpFirst = null;
for ( int i=0; i<100; i++ ) {
DataPoint dp = new DataPoint();
dp.setX( new BigDecimal(i * 0.1d).setScale(19, BigDecimal.ROUND_DOWN) );
dp.setY( new BigDecimal( Math.cos( dp.getX().doubleValue() ) ).setScale(19, BigDecimal.ROUND_DOWN) );
s.save(dp);
}
assertInsertCount( 0 );
assertUpdateCount( 0 );
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(true)
.scroll(ScrollMode.FORWARD_ONLY);
assertInsertCount( 100 );
assertUpdateCount( 0 );
clearCounts();
while ( sr.next() ) {
DataPoint dp = (DataPoint) sr.get();
assertFalse( s.isReadOnly( dp ) );
s.delete( dp );
}
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 100 );
}
@Test
public void testSaveReadOnlyModifyInSaveTransaction() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription( "original" );
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);
s.setReadOnly( dp, true );
dp.setDescription( "different" );
t.commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
t.commit();
assertInsertCount( 0 );
assertUpdateCount( 0 );
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
clearCounts();
}
@Test
public void testReadOnlyRefresh() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription( "original" );
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();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
t.commit();
assertInsertCount( 0 );
assertUpdateCount( 0 );
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
clearCounts();
}
@Test
public void testReadOnlyRefreshDetached() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dp = new DataPoint();
dp.setDescription( "original" );
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();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
s.setReadOnly( dp, true );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
t.commit();
assertInsertCount( 0 );
assertUpdateCount( 0 );
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
public void testReadOnlyDelete() {
clearCounts();
Session s = openSession();
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();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
@Test
public void testReadOnlyGetModifyAndDelete() {
clearCounts();
Session s = openSession();
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();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
dp.setDescription( "a DataPoint" );
s.delete( dp );
t.commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
clearCounts();
s = openSession();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertTrue( list.isEmpty() );
t.commit();
s.close();
}
@Test
public void testReadOnlyModeWithExistingModifiableEntity() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i=0; i<100; i++ ) {
dp = new DataPoint();
dp.setX( new BigDecimal(i * 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();
assertInsertCount( 100 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
DataPoint dpLast = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
int i = 0;
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(true)
.scroll(ScrollMode.FORWARD_ONLY);
int nExpectedChanges = 0;
while ( sr.next() ) {
dp = (DataPoint) sr.get();
if ( dp.getId() == dpLast.getId() ) {
//dpLast existed in the session before executing the read-only query
assertFalse( s.isReadOnly( dp ) );
}
else {
assertTrue( s.isReadOnly( dp ) );
}
if (++i==50) {
s.setReadOnly(dp, false);
nExpectedChanges = ( dp == dpLast ? 1 : 2 );
}
dp.setDescription("done!");
}
t.commit();
s.clear();
assertInsertCount( 0 );
assertUpdateCount( nExpectedChanges );
clearCounts();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( list.size(), nExpectedChanges );
assertEquals( 100, s.createQuery("delete from DataPoint").executeUpdate() );
t.commit();
s.close();
assertUpdateCount( 0 );
}
@Test
public void testModifiableModeWithExistingReadOnlyEntity() {
clearCounts();
Session s = openSession();
Transaction t = s.beginTransaction();
DataPoint dp = null;
for ( int i=0; i<100; i++ ) {
dp = new DataPoint();
dp.setX( new BigDecimal(i * 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();
assertInsertCount( 100 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
t = s.beginTransaction();
DataPoint dpLast = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertFalse( s.isReadOnly( dpLast ) );
s.setReadOnly( dpLast, true );
assertTrue( s.isReadOnly( dpLast ) );
dpLast.setDescription( "oy" );
int i = 0;
assertUpdateCount( 0 );
ScrollableResults sr = s.createQuery("from DataPoint dp order by dp.x asc")
.setReadOnly(false)
.scroll(ScrollMode.FORWARD_ONLY);
int nExpectedChanges = 0;
while ( sr.next() ) {
dp = (DataPoint) sr.get();
if ( dp.getId() == dpLast.getId() ) {
//dpLast existed in the session before executing the read-only query
assertTrue( s.isReadOnly( dp ) );
}
else {
assertFalse( s.isReadOnly( dp ) );
}
if (++i==50) {
s.setReadOnly(dp, true);
nExpectedChanges = ( dp == dpLast ? 99 : 98 );
}
dp.setDescription("done!");
}
t.commit();
s.clear();
assertUpdateCount( nExpectedChanges );
clearCounts();
t = s.beginTransaction();
List list = s.createQuery("from DataPoint where description='done!'").list();
assertEquals( list.size(), nExpectedChanges );
assertEquals( 100, s.createQuery("delete from DataPoint").executeUpdate() );
t.commit();
s.close();
assertUpdateCount( 0 );
}
@Test
public void testReadOnlyOnTextType() {
final String origText = "some huge text string";
final String newText = "some even bigger text string";
clearCounts();
Session s = openSession();
s.beginTransaction();
TextHolder holder = new TextHolder( origText );
s.save( holder );
Long id = holder.getId();
s.getTransaction().commit();
s.close();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
s = openSession();
s.beginTransaction();
holder = ( TextHolder ) s.get( TextHolder.class, id );
s.setReadOnly( holder, true );
holder.setTheText( newText );
s.flush();
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
s = openSession();
s.beginTransaction();
holder = ( TextHolder ) s.get( TextHolder.class, id );
assertEquals( "change written to database", origText, holder.getTheText() );
s.delete( holder );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
public void testMergeWithReadOnlyEntity() {
clearCounts();
Session s = openSession();
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();
assertInsertCount( 1 );
assertUpdateCount( 0 );
clearCounts();
dp.setDescription( "description" );
s = openSession();
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();
assertUpdateCount( 0 );
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();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
}

View File

@ -1,689 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.readonly;
import org.hibernate.Session;
import org.hibernate.testing.FailureExpected;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
/**
* @author Gail Badner
*/
public class ReadOnlyVersionedNodesTest extends AbstractReadOnlyTest {
@Override
public String[] getMappings() {
return new String[] { "readonly/VersionedNode.hbm.xml" };
}
@Test
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 );
clearCounts();
s = openSession();
s.beginTransaction();
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "diff-node-name", node.getName() );
assertEquals( 1, node.getVersion() );
s.setReadOnly( node, true );
s.delete( node );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
public void testUpdateSetReadOnlyTwice() 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() );
node.setName( "node-name" );
s.setReadOnly( node, true );
s.setReadOnly( node, true );
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() );
assertEquals( 0, node.getVersion() );
s.setReadOnly( node, true );
s.delete( node );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
public void testUpdateSetModifiable() 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() );
node.setName( "node-name" );
s.setReadOnly( node, false );
s.getTransaction().commit();
s.close();
assertUpdateCount( 1 );
assertInsertCount( 0 );
clearCounts();
s = openSession();
s.beginTransaction();
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
s.setReadOnly( node, true );
s.delete( node );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
@FailureExpected( jiraKey = "unknown" )
public void testUpdateSetReadOnlySetModifiable() 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() );
node.setName( "node-name" );
s.setReadOnly( node, true );
s.setReadOnly( node, false );
s.getTransaction().commit();
s.close();
assertUpdateCount( 1 );
assertInsertCount( 0 );
s = openSession();
s.beginTransaction();
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
s.delete( node );
s.getTransaction().commit();
s.close();
}
@Test
@FailureExpected( jiraKey = "unknown" )
public void testSetReadOnlyUpdateSetModifiable() 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.setReadOnly( node, false );
s.getTransaction().commit();
s.close();
assertUpdateCount( 1 );
assertInsertCount( 0 );
s = openSession();
s.beginTransaction();
node = ( VersionedNode ) s.get( VersionedNode.class, node.getId() );
assertEquals( "node-name", node.getName() );
assertEquals( 1, node.getVersion() );
s.delete( node );
s.getTransaction().commit();
s.close();
}
@Test
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( 1 );
assertInsertCount( 1 );
s = openSession();
s.beginTransaction();
parent = ( VersionedNode ) s.get( VersionedNode.class, parent.getId() );
assertEquals( "parent", parent.getName() );
assertEquals( 1, parent.getChildren().size() );
assertEquals( 1, parent.getVersion() );
child = ( VersionedNode ) s.get( VersionedNode.class, child.getId() );
assertNotNull( child );
s.delete( parent );
s.getTransaction().commit();
s.close();
}
@Test
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( 1 );
assertInsertCount( 1 );
clearCounts();
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( 1, parent.getVersion() );
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
s.setReadOnly( parent, true );
s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
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( 1 );
assertInsertCount( 1 );
clearCounts();
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( 1, parent.getVersion() );
assertSame( parent, child.getParent() );
assertSame( child, parent.getChildren().iterator().next() );
assertEquals( 0, child.getVersion() );
s.setReadOnly( parent, true );
s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
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( 1 );
assertInsertCount( 1 );
clearCounts();
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( 1, 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();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
public void testMergeUnchangedDetachedParentChildren() throws Exception {
Session s = openSession();
s.beginTransaction();
VersionedNode parent = new VersionedNode( "parent", "parent" );
VersionedNode child = new VersionedNode( "child", "child");
parent.addChild( child );
s.persist( parent );
s.getTransaction().commit();
s.close();
clearCounts();
s = openSession();
s.beginTransaction();
parent = ( VersionedNode ) s.merge( parent );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertInsertCount( 0 );
clearCounts();
s = openSession();
s.beginTransaction();
VersionedNode parentGet = ( VersionedNode ) s.get( parent.getClass(), parent.getId() );
s.merge( parent );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertInsertCount( 0 );
clearCounts();
s = openSession();
s.beginTransaction();
VersionedNode parentLoad = ( VersionedNode ) s.load( parent.getClass(), parent.getId() );
s.merge( parent );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertInsertCount( 0 );
clearCounts();
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();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
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( 1 );
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() );
assertNotNull( parent );
s.setReadOnly( child, true );
s.delete( child );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 1 );
}
@Test
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 );
clearCounts();
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.setReadOnly( parent, true );
s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
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 );
clearCounts();
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.setReadOnly( parent, true );
s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
@Test
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 );
clearCounts();
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.setReadOnly( parent, true );
s.setReadOnly( child, true );
s.delete( parent );
s.delete( child );
s.getTransaction().commit();
s.close();
assertUpdateCount( 0 );
assertDeleteCount( 2 );
}
protected void cleanupTest() throws Exception {
cleanup();
super.cleanupTest();
}
private void cleanup() {
Session s = sessionFactory().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();
}
}