HHH-4781 : Read-only entities changed to modifiable on refresh

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18643 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Gail Badner 2010-01-27 09:26:42 +00:00
parent 4ec26fa4cf
commit b40cfb58db
5 changed files with 363 additions and 4 deletions

View File

@ -71,7 +71,13 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) return; boolean isTransient = ! source.contains( event.getObject() );
if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) {
if ( isTransient ) {
source.setReadOnly( event.getObject(), source.isDefaultReadOnly() );
}
return;
}
final Object object = source.getPersistenceContext().unproxyAndReassociate( event.getObject() ); final Object object = source.getPersistenceContext().unproxyAndReassociate( event.getObject() );
@ -143,6 +149,9 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
String previousFetchProfile = source.getFetchProfile(); String previousFetchProfile = source.getFetchProfile();
source.setFetchProfile("refresh"); source.setFetchProfile("refresh");
Object result = persister.load( id, object, event.getLockOptions(), source ); Object result = persister.load( id, object, event.getLockOptions(), source );
// Keep the same read-only/modifiable setting for the entity that it had before refreshing;
// If it was transient, then set it to the default for the source.
source.setReadOnly( result, ( e == null ? source.isDefaultReadOnly() : e.isReadOnly() ) );
source.setFetchProfile(previousFetchProfile); source.setFetchProfile(previousFetchProfile);
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() ); UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );

View File

@ -840,6 +840,95 @@ public class ReadOnlyProxyTest extends FunctionalTestCase {
s.close(); s.close();
} }
public void testReadOnlyRefresh() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.load( DataPoint.class, dp.getId() );
s.setReadOnly( dp, true );
assertFalse( Hibernate.isInitialized( dp ) );
s.refresh( dp );
assertFalse( Hibernate.isInitialized( dp ) );
assertEquals( "original", dp.getDescription() );
assertTrue( Hibernate.isInitialized( dp ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
assertTrue( s.isReadOnly( dp ) );
assertTrue( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
assertTrue( s.isReadOnly( dp ) );
assertTrue( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
t.commit();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
public void testReadOnlyRefreshDetached() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
dp = ( DataPoint ) s.load( DataPoint.class, dp.getId() );
assertFalse( Hibernate.isInitialized( dp ) );
assertFalse( s.isReadOnly( dp ) );
s.setReadOnly( dp, true );
assertTrue( s.isReadOnly( dp ) );
s.evict( dp );
s.refresh( dp );
assertFalse( Hibernate.isInitialized( dp ) );
assertFalse( s.isReadOnly( dp ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
assertTrue( Hibernate.isInitialized( dp ) );
s.setReadOnly( dp, true );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
t.commit();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
public void testReadOnlyProxyMergeDetachedProxyWithChange() { public void testReadOnlyProxyMergeDetachedProxyWithChange() {
DataPoint dpOrig = createDataPoint( CacheMode.IGNORE ); DataPoint dpOrig = createDataPoint( CacheMode.IGNORE );

View File

@ -124,7 +124,7 @@ public class ReadOnlySessionLazyNonLazyTest extends FunctionalTestCase {
c = ( Container ) s.get( Container.class, cOrig.getId() ); c = ( Container ) s.get( Container.class, cOrig.getId() );
assertSame( cOrig, c ); assertSame( cOrig, c );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s ); checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
//s.refresh( cOrig ); s.refresh( cOrig );
assertSame( cOrig, c ); assertSame( cOrig, c );
checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s ); checkContainer( cOrig, expectedInitializedObjects, expectedReadOnlyObjects, s );
s.evict( cOrig ); s.evict( cOrig );

View File

@ -40,6 +40,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.junit.functional.FunctionalTestCase; import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite; import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.proxy.HibernateProxy;
/** /**
* *
@ -183,7 +184,7 @@ public class ReadOnlySessionTest extends FunctionalTestCase {
s.close(); s.close();
} }
public void testReadOnlyRefreshFailureExpected() { public void testReadOnlyRefresh() {
Session s = openSession(); Session s = openSession();
s.setCacheMode(CacheMode.IGNORE); s.setCacheMode(CacheMode.IGNORE);
@ -201,11 +202,18 @@ public class ReadOnlySessionTest extends FunctionalTestCase {
s.setDefaultReadOnly( true ); s.setDefaultReadOnly( true );
t = s.beginTransaction(); t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() ); dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertTrue( s.isReadOnly( dp ) );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertTrue( s.isReadOnly( dp ) );
assertEquals( "original", dp.getDescription() ); assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" ); dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() ); assertEquals( "changed", dp.getDescription() );
s.setDefaultReadOnly( false ); s.setDefaultReadOnly( false );
s.refresh( dp ); s.refresh( dp );
assertTrue( s.isReadOnly( dp ) );
assertEquals( "original", dp.getDescription() ); assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" ); dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() ); assertEquals( "changed", dp.getDescription() );
@ -218,7 +226,169 @@ public class ReadOnlySessionTest extends FunctionalTestCase {
s.delete( dp ); s.delete( dp );
t.commit(); t.commit();
s.close(); s.close();
}
public void testReadOnlyRefreshDetached() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( false );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.setDefaultReadOnly( true );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertTrue( s.isReadOnly( dp ) );
dp.setDescription( "changed" );
t.commit();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
public void testReadOnlyProxyRefresh() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
dp = ( DataPoint ) s.load( DataPoint.class, dp.getId() );
assertTrue( s.isReadOnly( dp ) );
assertFalse( Hibernate.isInitialized( dp ) );
s.refresh( dp );
assertFalse( Hibernate.isInitialized( dp ) );
assertTrue( s.isReadOnly( dp ) );
s.setDefaultReadOnly( false );
s.refresh( dp );
assertFalse( Hibernate.isInitialized( dp ) );
assertTrue( s.isReadOnly( dp ) );
assertEquals( "original", dp.getDescription() );
assertTrue( Hibernate.isInitialized( dp ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
assertTrue( s.isReadOnly( dp ) );
assertTrue( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertTrue( s.isReadOnly( dp ) );
assertTrue( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
s.setDefaultReadOnly( true );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.refresh( dp );
assertTrue( s.isReadOnly( dp ) );
assertTrue( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
assertEquals( "original", dp.getDescription() );
dp.setDescription( "changed" );
t.commit();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
public void testReadOnlyProxyRefreshDetached() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
t = s.beginTransaction();
s.setDefaultReadOnly( true );
dp = ( DataPoint ) s.load( DataPoint.class, dp.getId() );
assertFalse( Hibernate.isInitialized( dp ) );
assertTrue( s.isReadOnly( dp ) );
s.evict( dp );
s.refresh( dp );
assertFalse( Hibernate.isInitialized( dp ) );
s.setDefaultReadOnly( false );
assertTrue( s.isReadOnly( dp ) );
s.evict( dp );
s.refresh( dp );
assertFalse( Hibernate.isInitialized( dp ) );
assertFalse( s.isReadOnly( dp ) );
assertFalse( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
assertTrue( Hibernate.isInitialized( dp ) );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertFalse( s.isReadOnly( dp ) );
assertFalse( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
s.setDefaultReadOnly( true );
s.evict( dp );
s.refresh( dp );
assertEquals( "original", dp.getDescription() );
assertTrue( s.isReadOnly( dp ) );
assertTrue( s.isReadOnly( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getImplementation() ) );
dp.setDescription( "changed" );
assertEquals( "changed", dp.getDescription() );
t.commit();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
} }
public void testReadOnlyDelete() { public void testReadOnlyDelete() {
@ -453,4 +623,56 @@ public class ReadOnlySessionTest extends FunctionalTestCase {
s.close(); s.close();
} }
public void testMergeWithReadOnlyProxy() {
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();
s.setDefaultReadOnly( true );
DataPoint dpProxy = ( DataPoint ) s.load( DataPoint.class, new Long( dp.getId() ) );
assertTrue( s.isReadOnly( dpProxy ) );
assertFalse( Hibernate.isInitialized( dpProxy ) );
s.evict( dpProxy );
dpProxy = ( DataPoint ) s.merge( dpProxy );
assertTrue( s.isReadOnly( dpProxy ) );
assertFalse( Hibernate.isInitialized( dpProxy ) );
dpProxy = ( DataPoint ) s.merge( dp );
assertTrue( s.isReadOnly( dpProxy ) );
assertTrue( Hibernate.isInitialized( dpProxy ) );
assertEquals( "description", dpProxy.getDescription() );
s.evict( dpProxy );
dpProxy = ( DataPoint ) s.merge( dpProxy );
assertTrue( s.isReadOnly( dpProxy ) );
assertTrue( Hibernate.isInitialized( dpProxy ) );
assertEquals( "description", dpProxy.getDescription() );
dpProxy.setDescription( null );
dpProxy = ( DataPoint ) s.merge( dp );
assertTrue( s.isReadOnly( dpProxy ) );
assertTrue( Hibernate.isInitialized( dpProxy ) );
assertEquals( "description", dpProxy.getDescription() );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, new Long( dp.getId() ) );
assertNull( dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
} }

View File

@ -169,7 +169,7 @@ public class ReadOnlyTest extends FunctionalTestCase {
} }
public void testReadOnlyRefreshFailureExpected() { public void testReadOnlyRefresh() {
Session s = openSession(); Session s = openSession();
s.setCacheMode(CacheMode.IGNORE); s.setCacheMode(CacheMode.IGNORE);
@ -206,6 +206,45 @@ public class ReadOnlyTest extends FunctionalTestCase {
} }
public void testReadOnlyRefreshDetached() {
Session s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s = openSession();
s.setCacheMode(CacheMode.IGNORE);
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();
s.clear();
t = s.beginTransaction();
dp = ( DataPoint ) s.get( DataPoint.class, dp.getId() );
assertEquals( "original", dp.getDescription() );
s.delete( dp );
t.commit();
s.close();
}
public void testReadOnlyDelete() { public void testReadOnlyDelete() {
Session s = openSession(); Session s = openSession();