HHH-16193 LazyInitializationException when accessing loaded reference after session is closed using bytecode enhancement

This commit is contained in:
Andrea Boriero 2023-02-20 20:11:29 +01:00 committed by Christian Beikov
parent 4470e74da3
commit 46c9da1a46
3 changed files with 23 additions and 21 deletions

View File

@ -12,11 +12,13 @@ import org.hibernate.NonUniqueObjectException;
import org.hibernate.PersistentObjectException; import org.hibernate.PersistentObjectException;
import org.hibernate.TypeMismatchException; import org.hibernate.TypeMismatchException;
import org.hibernate.action.internal.DelayedPostInsertIdentifier; import org.hibernate.action.internal.DelayedPostInsertIdentifier;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.LoadEvent; import org.hibernate.event.spi.LoadEvent;
@ -38,6 +40,9 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
/** /**
* Defines the default load event listeners used by hibernate for loading entities * Defines the default load event listeners used by hibernate for loading entities
* in response to generated load events. * in response to generated load events.
@ -530,7 +535,16 @@ public class DefaultLoadEventListener implements LoadEventListener {
= CacheEntityLoaderHelper.INSTANCE.loadFromSessionCache( event, keyToLoad, options ); = CacheEntityLoaderHelper.INSTANCE.loadFromSessionCache( event, keyToLoad, options );
final Object entity = persistenceContextEntry.getEntity(); final Object entity = persistenceContextEntry.getEntity();
if ( entity != null ) { if ( entity != null ) {
return persistenceContextEntry.isManaged() ? entity : null; if ( persistenceContextEntry.isManaged() ) {
if ( isPersistentAttributeInterceptable( entity ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
( (EnhancementAsProxyLazinessInterceptor) interceptor ).forceInitialize( entity, null );
}
}
return entity;
}
return null;
} }
else { else {
return load( event, persister, keyToLoad ); return load( event, persister, keyToLoad );

View File

@ -70,16 +70,14 @@ public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEn
entityInstance = loadingEntityEntry.getEntityInstance(); entityInstance = loadingEntityEntry.getEntityInstance();
} }
else { else {
if ( entityInstance == null ) { // Force creating a proxy
// Force creating a proxy entityInstance = session.internalLoad(
entityInstance = session.internalLoad( entityKey.getEntityName(),
entityKey.getEntityName(), entityKey.getIdentifier(),
entityKey.getIdentifier(), false,
false, false
false );
); toBatchLoad.add( entityKey );
toBatchLoad.add( entityKey );
}
} }
} }
} }

View File

@ -10,10 +10,8 @@ import java.util.function.Consumer;
import org.hibernate.FetchNotFoundException; import org.hibernate.FetchNotFoundException;
import org.hibernate.annotations.NotFoundAction; import org.hibernate.annotations.NotFoundAction;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper; import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
@ -33,8 +31,6 @@ import org.hibernate.sql.results.graph.entity.EntityLoadingLogging;
import org.hibernate.sql.results.graph.entity.LoadingEntityEntry; import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.internal.log.LoggingHelper.toLoggableString; import static org.hibernate.internal.log.LoggingHelper.toLoggableString;
/** /**
@ -138,12 +134,6 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
entityInstance = persistenceContext.getEntity( entityKey ); entityInstance = persistenceContext.getEntity( entityKey );
if ( entityInstance != null ) { if ( entityInstance != null ) {
if ( isPersistentAttributeInterceptable( entityInstance ) ) {
final PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable( entityInstance ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
( (EnhancementAsProxyLazinessInterceptor) interceptor ).forceInitialize( entityInstance, null );
}
}
isInitialized = true; isInitialized = true;
return; return;
} }