HHH-16469 Hibernate repeatedly issues identical SELECT queries to load an optional one-to-one association

This commit is contained in:
Andrea Boriero 2023-05-02 10:05:52 +02:00 committed by Christian Beikov
parent 4e9586abc1
commit d503b55bde
4 changed files with 36 additions and 22 deletions

View File

@ -513,8 +513,8 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
if ( existingEntity != null ) { if ( existingEntity != null ) {
entityInstance = existingEntity; entityInstance = existingEntity;
if ( existingLoadingEntry == null && isExistingEntityInitialized( existingEntity ) ) { if ( existingLoadingEntry == null && isExistingEntityInitialized( existingEntity ) ) {
notifyResolutionListeners( entityInstance );
this.isInitialized = true; this.isInitialized = true;
notifyResolutionListeners( entityInstance );
} }
} }
else if ( entityInstanceFromExecutionContext != null ) { else if ( entityInstanceFromExecutionContext != null ) {

View File

@ -40,7 +40,7 @@ public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelect
protected void registerResolutionListener() { protected void registerResolutionListener() {
parentAccess.registerResolutionListener( parentInstance -> { parentAccess.registerResolutionListener( parentInstance -> {
final AttributeMapping parentAttribute = getParentEntityAttribute( referencedModelPart.getAttributeName() ); final AttributeMapping parentAttribute = getParentEntityAttribute( referencedModelPart.getAttributeName() );
if ( parentAttribute != null ) { if ( parentAttribute != null && !firstEntityInitializer.isEntityInitialized() ) {
getParentInfos().add( new ParentInfo( parentInstance, parentAttribute.getStateArrayPosition() ) ); getParentInfos().add( new ParentInfo( parentInstance, parentAttribute.getStateArrayPosition() ) );
} }
} ); } );

View File

@ -31,6 +31,7 @@ import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.graph.entity.EntityLoadingLogging; 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 org.hibernate.sql.results.spi.LoadContexts;
import static org.hibernate.internal.log.LoggingHelper.toLoggableString; import static org.hibernate.internal.log.LoggingHelper.toLoggableString;
@ -139,10 +140,8 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
return; return;
} }
final LoadingEntityEntry existingLoadingEntry = session final LoadContexts loadContexts = session.getPersistenceContext().getLoadContexts();
.getPersistenceContext() final LoadingEntityEntry existingLoadingEntry = loadContexts.findLoadingEntityEntry( entityKey );
.getLoadContexts()
.findLoadingEntityEntry( entityKey );
if ( existingLoadingEntry != null ) { if ( existingLoadingEntry != null ) {
if ( EntityLoadingLogging.DEBUG_ENABLED ) { if ( EntityLoadingLogging.DEBUG_ENABLED ) {
@ -157,14 +156,15 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
} }
this.entityInstance = existingLoadingEntry.getEntityInstance(); this.entityInstance = existingLoadingEntry.getEntityInstance();
if ( existingLoadingEntry.getEntityInitializer() != this ) { final EntityInitializer entityInitializer = existingLoadingEntry.getEntityInitializer();
if ( entityInitializer != this ) {
// the entity is already being loaded elsewhere // the entity is already being loaded elsewhere
if ( EntityLoadingLogging.DEBUG_ENABLED ) { if ( EntityLoadingLogging.DEBUG_ENABLED ) {
EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf(
"(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing", "(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing",
CONCRETE_NAME, CONCRETE_NAME,
toLoggableString( getNavigablePath(), entityIdentifier ), toLoggableString( getNavigablePath(), entityIdentifier ),
existingLoadingEntry.getEntityInitializer() entityInitializer
); );
} }
@ -172,6 +172,12 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
isInitialized = true; isInitialized = true;
return; return;
} }
else {
if ( entityInstance == null ) {
isInitialized = true;
return;
}
}
} }
if ( EntityLoadingLogging.DEBUG_ENABLED ) { if ( EntityLoadingLogging.DEBUG_ENABLED ) {
@ -193,6 +199,11 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
if ( toOneMapping.getNotFoundAction() == NotFoundAction.EXCEPTION ) { if ( toOneMapping.getNotFoundAction() == NotFoundAction.EXCEPTION ) {
throw new FetchNotFoundException( entityName, entityIdentifier ); throw new FetchNotFoundException( entityName, entityIdentifier );
} }
rowProcessingState.getJdbcValuesSourceProcessingState()
.registerLoadingEntity(
entityKey,
new LoadingEntityEntry( this, entityKey, concreteDescriptor, entityInstance )
);
} }
if ( EntityLoadingLogging.DEBUG_ENABLED ) { if ( EntityLoadingLogging.DEBUG_ENABLED ) {
@ -209,6 +220,7 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl
if ( lazyInitializer != null ) { if ( lazyInitializer != null ) {
lazyInitializer.setUnwrap( unwrapProxy ); lazyInitializer.setUnwrap( unwrapProxy );
} }
isInitialized = true; isInitialized = true;
} }

View File

@ -174,6 +174,7 @@ public class JdbcValuesSourceProcessingStateStandardImpl implements JdbcValuesSo
loadingEntityMap.forEach( loadingEntityMap.forEach(
(entityKey, loadingEntityEntry) -> { (entityKey, loadingEntityEntry) -> {
if ( loadingEntityEntry.getEntityInstance() != null ) {
if ( postLoadEvent != null ) { if ( postLoadEvent != null ) {
postLoadEvent.reset(); postLoadEvent.reset();
postLoadEvent.setEntity( loadingEntityEntry.getEntityInstance() ) postLoadEvent.setEntity( loadingEntityEntry.getEntityInstance() )
@ -191,6 +192,7 @@ public class JdbcValuesSourceProcessingStateStandardImpl implements JdbcValuesSo
); );
} }
} }
}
); );
loadingEntityMap = null; loadingEntityMap = null;
} }