HHH-1645 HHH-17395 Refresh with LockMode on an unitialized proxy does not work
This commit is contained in:
parent
839c695c8e
commit
d085936fcb
|
@ -33,6 +33,8 @@ import org.hibernate.loader.ast.spi.CascadingFetchProfile;
|
||||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
import org.hibernate.proxy.LazyInitializer;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
@ -62,7 +64,22 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
||||||
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
||||||
final Object object = event.getObject();
|
final Object object = event.getObject();
|
||||||
if ( persistenceContext.reassociateIfUninitializedProxy( object ) ) {
|
if ( persistenceContext.reassociateIfUninitializedProxy( object ) ) {
|
||||||
if ( isTransient( event, source, object ) ) {
|
final boolean isTransient = isTransient( event, source, object );
|
||||||
|
|
||||||
|
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
|
||||||
|
final EntityPersister persister = source.getEntityPersister( lazyInitializer.getEntityName(), object );
|
||||||
|
refresh(
|
||||||
|
event,
|
||||||
|
null,
|
||||||
|
source,
|
||||||
|
persister,
|
||||||
|
lazyInitializer,
|
||||||
|
null,
|
||||||
|
persister.getIdentifier( object, event.getSession() ),
|
||||||
|
persistenceContext
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( isTransient ) {
|
||||||
source.setReadOnly( object, source.isDefaultReadOnly() );
|
source.setReadOnly( object, source.isDefaultReadOnly() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,9 +161,22 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
||||||
evictEntity( object, persister, id, source );
|
evictEntity( object, persister, id, source );
|
||||||
evictCachedCollections( persister, id, source );
|
evictCachedCollections( persister, id, source );
|
||||||
|
|
||||||
|
refresh( event, object, source, persister, null, entry, id, persistenceContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void refresh(
|
||||||
|
RefreshEvent event,
|
||||||
|
Object object,
|
||||||
|
EventSource source,
|
||||||
|
EntityPersister persister,
|
||||||
|
LazyInitializer lazyInitializer,
|
||||||
|
EntityEntry entry,
|
||||||
|
Object id,
|
||||||
|
PersistenceContext persistenceContext) {
|
||||||
|
|
||||||
final Object result = source.getLoadQueryInfluencers().fromInternalFetchProfile(
|
final Object result = source.getLoadQueryInfluencers().fromInternalFetchProfile(
|
||||||
CascadingFetchProfile.REFRESH,
|
CascadingFetchProfile.REFRESH,
|
||||||
() -> doRefresh( event, source, object, entry, persister, id, persistenceContext )
|
() -> doRefresh( event, source, object, entry, persister, lazyInitializer, id, persistenceContext )
|
||||||
);
|
);
|
||||||
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
|
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
|
||||||
}
|
}
|
||||||
|
@ -179,6 +209,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
||||||
Object object,
|
Object object,
|
||||||
EntityEntry entry,
|
EntityEntry entry,
|
||||||
EntityPersister persister,
|
EntityPersister persister,
|
||||||
|
LazyInitializer lazyInitializer,
|
||||||
Object id,
|
Object id,
|
||||||
PersistenceContext persistenceContext) {
|
PersistenceContext persistenceContext) {
|
||||||
// Handle the requested lock-mode (if one) in relation to the entry's (if one) current lock-mode
|
// Handle the requested lock-mode (if one) in relation to the entry's (if one) current lock-mode
|
||||||
|
@ -228,19 +259,32 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
||||||
persistenceContext.getEntry( result ).setLockMode( postRefreshLockMode );
|
persistenceContext.getEntry( result ).setLockMode( postRefreshLockMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the same read-only/modifiable setting for the entity that it had before refreshing;
|
source.setReadOnly( result, isReadOnly( entry, persister, lazyInitializer, source ) );
|
||||||
// If it was transient, then set it to the default for the source.
|
|
||||||
if ( !persister.isMutable() ) {
|
|
||||||
// this is probably redundant; it should already be read-only
|
|
||||||
source.setReadOnly( result, true );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
source.setReadOnly( result, entry == null ? source.isDefaultReadOnly() : entry.isReadOnly() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isReadOnly(
|
||||||
|
EntityEntry entry,
|
||||||
|
EntityPersister persister,
|
||||||
|
LazyInitializer lazyInitializer,
|
||||||
|
EventSource 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.
|
||||||
|
if ( !persister.isMutable() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( entry != null ) {
|
||||||
|
return entry.isReadOnly();
|
||||||
|
}
|
||||||
|
else if ( lazyInitializer != null ) {
|
||||||
|
return lazyInitializer.isReadOnly();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return source.isDefaultReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void evictCachedCollections(EntityPersister persister, Object id, EventSource source) {
|
private static void evictCachedCollections(EntityPersister persister, Object id, EventSource source) {
|
||||||
evictCachedCollections( persister.getPropertyTypes(), id, source );
|
evictCachedCollections( persister.getPropertyTypes(), id, source );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1102,7 +1102,7 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
|
||||||
s.setReadOnly( dp, true );
|
s.setReadOnly( dp, true );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertFalse( Hibernate.isInitialized( dp ) );
|
||||||
s.refresh( dp );
|
s.refresh( dp );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
assertEquals( "original", dp.getDescription() );
|
assertEquals( "original", dp.getDescription() );
|
||||||
assertTrue( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
dp.setDescription( "changed" );
|
dp.setDescription( "changed" );
|
||||||
|
@ -1232,7 +1232,7 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
|
||||||
assertTrue( s.isReadOnly( dp ) );
|
assertTrue( s.isReadOnly( dp ) );
|
||||||
s.evict( dp );
|
s.evict( dp );
|
||||||
s.refresh( dp );
|
s.refresh( dp );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
assertFalse( s.isReadOnly( dp ) );
|
assertFalse( s.isReadOnly( dp ) );
|
||||||
dp.setDescription( "changed" );
|
dp.setDescription( "changed" );
|
||||||
assertEquals( "changed", dp.getDescription() );
|
assertEquals( "changed", dp.getDescription() );
|
||||||
|
|
|
@ -516,11 +516,11 @@ public class ReadOnlySessionTest extends AbstractReadOnlyTest {
|
||||||
assertTrue( s.isReadOnly( dp ) );
|
assertTrue( s.isReadOnly( dp ) );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertFalse( Hibernate.isInitialized( dp ) );
|
||||||
s.refresh( dp );
|
s.refresh( dp );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
assertTrue( s.isReadOnly( dp ) );
|
assertTrue( s.isReadOnly( dp ) );
|
||||||
s.setDefaultReadOnly( false );
|
s.setDefaultReadOnly( false );
|
||||||
s.refresh( dp );
|
s.refresh( dp );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
assertTrue( s.isReadOnly( dp ) );
|
assertTrue( s.isReadOnly( dp ) );
|
||||||
assertEquals( "original", dp.getDescription() );
|
assertEquals( "original", dp.getDescription() );
|
||||||
assertTrue( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
|
@ -574,12 +574,12 @@ public class ReadOnlySessionTest extends AbstractReadOnlyTest {
|
||||||
assertTrue( s.isReadOnly( dp ) );
|
assertTrue( s.isReadOnly( dp ) );
|
||||||
s.evict( dp );
|
s.evict( dp );
|
||||||
s.refresh( dp );
|
s.refresh( dp );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
s.setDefaultReadOnly( false );
|
s.setDefaultReadOnly( false );
|
||||||
assertTrue( s.isReadOnly( dp ) );
|
assertTrue( s.isReadOnly( dp ) );
|
||||||
s.evict( dp );
|
s.evict( dp );
|
||||||
s.refresh( dp );
|
s.refresh( dp );
|
||||||
assertFalse( Hibernate.isInitialized( dp ) );
|
assertTrue( Hibernate.isInitialized( dp ) );
|
||||||
assertFalse( s.isReadOnly( dp ) );
|
assertFalse( s.isReadOnly( dp ) );
|
||||||
assertFalse( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) );
|
assertFalse( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) );
|
||||||
dp.setDescription( "changed" );
|
dp.setDescription( "changed" );
|
||||||
|
|
Loading…
Reference in New Issue