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 ) {
entityInstance = existingEntity;
if ( existingLoadingEntry == null && isExistingEntityInitialized( existingEntity ) ) {
notifyResolutionListeners( entityInstance );
this.isInitialized = true;
notifyResolutionListeners( entityInstance );
}
}
else if ( entityInstanceFromExecutionContext != null ) {

View File

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

View File

@ -174,21 +174,23 @@ public class JdbcValuesSourceProcessingStateStandardImpl implements JdbcValuesSo
loadingEntityMap.forEach(
(entityKey, loadingEntityEntry) -> {
if ( postLoadEvent != null ) {
postLoadEvent.reset();
postLoadEvent.setEntity( loadingEntityEntry.getEntityInstance() )
.setId( entityKey.getIdentifier() )
.setPersister( loadingEntityEntry.getDescriptor() );
listenerGroup.fireEventOnEachListener( postLoadEvent, PostLoadEventListener::onPostLoad );
}
if ( loadingEntityEntry.getEntityInstance() != null ) {
if ( postLoadEvent != null ) {
postLoadEvent.reset();
postLoadEvent.setEntity( loadingEntityEntry.getEntityInstance() )
.setId( entityKey.getIdentifier() )
.setPersister( loadingEntityEntry.getDescriptor() );
listenerGroup.fireEventOnEachListener( postLoadEvent, PostLoadEventListener::onPostLoad );
}
final Callback callback = executionContext.getCallback();
if ( callback != null ) {
callback.invokeAfterLoadActions(
loadingEntityEntry.getEntityInstance(),
loadingEntityEntry.getDescriptor(),
getSession()
);
final Callback callback = executionContext.getCallback();
if ( callback != null ) {
callback.invokeAfterLoadActions(
loadingEntityEntry.getEntityInstance(),
loadingEntityEntry.getDescriptor(),
getSession()
);
}
}
}
);