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.persister.collection.CollectionPersister;
|
||||
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.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -62,7 +64,22 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
||||
final Object object = event.getObject();
|
||||
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() );
|
||||
}
|
||||
}
|
||||
|
@ -144,9 +161,22 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
evictEntity( object, 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(
|
||||
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() );
|
||||
}
|
||||
|
@ -179,6 +209,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
Object object,
|
||||
EntityEntry entry,
|
||||
EntityPersister persister,
|
||||
LazyInitializer lazyInitializer,
|
||||
Object id,
|
||||
PersistenceContext persistenceContext) {
|
||||
// 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 );
|
||||
}
|
||||
|
||||
// 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() ) {
|
||||
// this is probably redundant; it should already be read-only
|
||||
source.setReadOnly( result, true );
|
||||
}
|
||||
else {
|
||||
source.setReadOnly( result, entry == null ? source.isDefaultReadOnly() : entry.isReadOnly() );
|
||||
}
|
||||
source.setReadOnly( result, isReadOnly( entry, persister, lazyInitializer, source ) );
|
||||
}
|
||||
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) {
|
||||
evictCachedCollections( persister.getPropertyTypes(), id, source );
|
||||
}
|
||||
|
|
|
@ -1102,7 +1102,7 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
|
|||
s.setReadOnly( dp, true );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
s.refresh( dp );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
assertEquals( "original", dp.getDescription() );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
dp.setDescription( "changed" );
|
||||
|
@ -1232,7 +1232,7 @@ public class ReadOnlyProxyTest extends AbstractReadOnlyTest {
|
|||
assertTrue( s.isReadOnly( dp ) );
|
||||
s.evict( dp );
|
||||
s.refresh( dp );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
assertFalse( s.isReadOnly( dp ) );
|
||||
dp.setDescription( "changed" );
|
||||
assertEquals( "changed", dp.getDescription() );
|
||||
|
|
|
@ -516,11 +516,11 @@ public class ReadOnlySessionTest extends AbstractReadOnlyTest {
|
|||
assertTrue( s.isReadOnly( dp ) );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
s.refresh( dp );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( s.isReadOnly( dp ) );
|
||||
s.setDefaultReadOnly( false );
|
||||
s.refresh( dp );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( s.isReadOnly( dp ) );
|
||||
assertEquals( "original", dp.getDescription() );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
|
@ -574,12 +574,12 @@ public class ReadOnlySessionTest extends AbstractReadOnlyTest {
|
|||
assertTrue( s.isReadOnly( dp ) );
|
||||
s.evict( dp );
|
||||
s.refresh( dp );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
s.setDefaultReadOnly( false );
|
||||
assertTrue( s.isReadOnly( dp ) );
|
||||
s.evict( dp );
|
||||
s.refresh( dp );
|
||||
assertFalse( Hibernate.isInitialized( dp ) );
|
||||
assertTrue( Hibernate.isInitialized( dp ) );
|
||||
assertFalse( s.isReadOnly( dp ) );
|
||||
assertFalse( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) );
|
||||
dp.setDescription( "changed" );
|
||||
|
|
Loading…
Reference in New Issue