From a4e9123ceb4088882796d9b78e489c16f7a1af37 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 12 Jun 2025 12:29:08 +0200 Subject: [PATCH] some minor refactorings to Initializers --- ...ractBatchEntitySelectFetchInitializer.java | 259 ++++++++-------- ...nsideEmbeddableSelectFetchInitializer.java | 39 ++- .../BatchEntitySelectFetchInitializer.java | 33 +-- ...nitializeEntitySelectFetchInitializer.java | 10 +- .../DiscriminatedEntityInitializer.java | 30 +- .../EntityDelayedFetchInitializer.java | 55 ++-- .../internal/EntityInitializerImpl.java | 278 +++++++++--------- ...titySelectFetchByUniqueKeyInitializer.java | 42 +-- .../EntitySelectFetchInitializer.java | 173 ++++++----- 9 files changed, 448 insertions(+), 471 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java index 4f3db569faf4..6280f47b0c6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java @@ -11,13 +11,11 @@ import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; @@ -39,7 +37,8 @@ public abstract class AbstractBatchEntitySelectFetchInitializer owningEntityInitializer; - public static abstract class AbstractBatchEntitySelectFetchInitializerData extends EntitySelectFetchInitializerData { + public static abstract class AbstractBatchEntitySelectFetchInitializerData + extends EntitySelectFetchInitializerData { final boolean batchDisabled; // per-row state @@ -48,10 +47,11 @@ public static abstract class AbstractBatchEntitySelectFetchInitializerData exten public AbstractBatchEntitySelectFetchInitializerData( AbstractBatchEntitySelectFetchInitializer initializer, RowProcessingState rowProcessingState) { - super( initializer, rowProcessingState ); + super( rowProcessingState ); batchDisabled = rowProcessingState.isScrollResult() - || !rowProcessingState.getLoadQueryInfluencers().effectivelyBatchLoadable( initializer.toOneMapping.getEntityMappingType().getEntityPersister() ); + || !rowProcessingState.getLoadQueryInfluencers() + .effectivelyBatchLoadable( initializer.toOneMapping.getEntityMappingType().getEntityPersister() ); } } @@ -65,7 +65,9 @@ public AbstractBatchEntitySelectFetchInitializer( AssemblerCreationState creationState) { super( parent, toOneMapping, fetchedNavigable, concreteDescriptor, keyResult, affectedByFilter, creationState ); //noinspection unchecked - this.owningEntityInitializer = (EntityInitializer) Initializer.findOwningEntityInitializer( parent ); + this.owningEntityInitializer = + (EntityInitializer) + Initializer.findOwningEntityInitializer( parent ); assert owningEntityInitializer != null : "This initializer requires an owning parent entity initializer"; } @@ -73,58 +75,54 @@ public AbstractBatchEntitySelectFetchInitializer( @Override public void resolveKey(Data data) { - if ( data.getState() != State.UNINITIALIZED ) { - return; - } - - data.entityKey = null; - data.setInstance( null ); - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - //noinspection unchecked - final Initializer initializer = (Initializer) keyAssembler.getInitializer(); - if ( initializer != null ) { - final InitializerData subData = initializer.getData( rowProcessingState ); - initializer.resolveKey( subData ); - data.entityIdentifier = null; - data.setState( subData.getState() == State.MISSING ? State.MISSING : State.KEY_RESOLVED ); - } - else { - data.entityIdentifier = keyAssembler.assemble( rowProcessingState ); - data.setState( data.entityIdentifier == null ? State.MISSING : State.KEY_RESOLVED ); + if ( data.getState() == State.UNINITIALIZED ) { + data.entityKey = null; + data.setInstance( null ); + final var rowProcessingState = data.getRowProcessingState(); + //noinspection unchecked + final Initializer initializer = (Initializer) keyAssembler.getInitializer(); + if ( initializer != null ) { + final InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + data.entityIdentifier = null; + data.setState( subData.getState() == State.MISSING ? State.MISSING : State.KEY_RESOLVED ); + } + else { + data.entityIdentifier = keyAssembler.assemble( rowProcessingState ); + data.setState( data.entityIdentifier == null ? State.MISSING : State.KEY_RESOLVED ); + } } } @Override public void resolveInstance(Data data) { - if ( data.getState() != State.KEY_RESOLVED ) { - return; - } - - data.setState( State.RESOLVED ); - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - if ( data.entityIdentifier == null ) { - // entityIdentifier can be null if the identifier is based on an initializer - data.entityIdentifier = keyAssembler.assemble( rowProcessingState ); + if ( data.getState() == State.KEY_RESOLVED ) { + data.setState( State.RESOLVED ); + final var rowProcessingState = data.getRowProcessingState(); if ( data.entityIdentifier == null ) { - data.entityKey = null; - data.setInstance( null ); - data.setState( State.MISSING ); - return; + // entityIdentifier can be null if the identifier is based on an initializer + data.entityIdentifier = keyAssembler.assemble( rowProcessingState ); + if ( data.entityIdentifier == null ) { + data.entityKey = null; + data.setInstance( null ); + data.setState( State.MISSING ); + return; + } } + resolveInstanceFromIdentifier( data ); } - resolveInstanceFromIdentifier( data ); } protected void resolveInstanceFromIdentifier(Data data) { if ( data.batchDisabled ) { - initialize( data ); + initializeIfNecessary( data ); } else { data.entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor ); data.setInstance( getExistingInitializedInstance( data ) ); if ( data.getInstance() == null ) { - // need to add the key to the batch queue only when the entity has not been already loaded or - // there isn't another initializer that is loading it + // need to add the key to the batch queue only when the entity has not + // already been loaded or there's no other initializer that's loading it registerToBatchFetchQueue( data ); } } @@ -136,87 +134,92 @@ public void resolveInstance(Object instance, Data data) { data.setState( State.MISSING ); data.entityKey = null; data.setInstance( null ); - return; } - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - // Only need to extract the identifier if the identifier has a many to one - final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); - data.entityKey = null; - data.entityIdentifier = null; - if ( lazyInitializer == null ) { - // Entity is most probably initialized - data.setInstance( instance ); - if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() - && isPersistentAttributeInterceptable( instance ) - && getAttributeInterceptor( instance ) - instanceof EnhancementAsProxyLazinessInterceptor enhancementInterceptor ) { - if ( enhancementInterceptor.isInitialized() ) { - data.setState( State.INITIALIZED ); + else { + final var rowProcessingState = data.getRowProcessingState(); + // Only need to extract the identifier if the identifier has a many-to-one + final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); + data.entityKey = null; + data.entityIdentifier = null; + if ( lazyInitializer == null ) { + // Entity is most probably initialized + data.setInstance( instance ); + if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() + && isPersistentAttributeInterceptable( instance ) + && getAttributeInterceptor( instance ) + instanceof EnhancementAsProxyLazinessInterceptor enhancementInterceptor ) { + if ( enhancementInterceptor.isInitialized() ) { + data.setState( State.INITIALIZED ); + } + else { + data.setState( State.RESOLVED ); + data.entityIdentifier = enhancementInterceptor.getIdentifier(); + } + if ( keyIsEager && data.entityIdentifier == null ) { + data.entityIdentifier = + concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() ); + } } else { + // If the entity initializer is null, we know the entity is fully initialized. + // Otherwise, it will be initialized by some other initializer. data.setState( State.RESOLVED ); - data.entityIdentifier = enhancementInterceptor.getIdentifier(); + data.entityIdentifier = + concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() ); } } - else { - // If the entity initializer is null, we know the entity is fully initialized, - // otherwise it will be initialized by some other initializer + else if ( lazyInitializer.isUninitialized() ) { data.setState( State.RESOLVED ); - data.entityIdentifier = concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() ); + data.entityIdentifier = lazyInitializer.getInternalIdentifier(); } - if ( keyIsEager && data.entityIdentifier == null ) { - data.entityIdentifier = concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() ); + else { + // Entity is initialized + data.setState( State.INITIALIZED ); + if ( keyIsEager ) { + data.entityIdentifier = lazyInitializer.getInternalIdentifier(); + } + data.setInstance( lazyInitializer.getImplementation() ); + } + + if ( data.getState() == State.RESOLVED ) { + resolveInstanceFromIdentifier( data ); } - } - else if ( lazyInitializer.isUninitialized() ) { - data.setState( State.RESOLVED ); - data.entityIdentifier = lazyInitializer.getInternalIdentifier(); - } - else { - // Entity is initialized - data.setState( State.INITIALIZED ); if ( keyIsEager ) { - data.entityIdentifier = lazyInitializer.getInternalIdentifier(); + final Initializer initializer = keyAssembler.getInitializer(); + assert initializer != null; + initializer.resolveInstance( data.entityIdentifier, rowProcessingState ); + } + else if ( rowProcessingState.needsResolveState() ) { + // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit + keyAssembler.resolveState( rowProcessingState ); } - data.setInstance( lazyInitializer.getImplementation() ); - } - - if ( data.getState() == State.RESOLVED ) { - resolveInstanceFromIdentifier( data ); - } - if ( keyIsEager ) { - final Initializer initializer = keyAssembler.getInitializer(); - assert initializer != null; - initializer.resolveInstance( data.entityIdentifier, rowProcessingState ); - } - else if ( rowProcessingState.needsResolveState() ) { - // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit - keyAssembler.resolveState( rowProcessingState ); } } @Override public void initializeInstance(Data data) { - if ( data.getState() != State.RESOLVED ) { - return; - } - data.setState( State.INITIALIZED ); - if ( data.batchDisabled ) { - Hibernate.initialize( data.getInstance() ); + if ( data.getState() == State.RESOLVED ) { + data.setState( State.INITIALIZED ); + if ( data.batchDisabled ) { + Hibernate.initialize( data.getInstance() ); + } } } protected Object getExistingInitializedInstance(Data data) { - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - final EntityHolder holder = persistenceContext.getEntityHolder( data.entityKey ); + final EntityHolder holder = + data.getRowProcessingState().getSession() + .getPersistenceContextInternal() + .getEntityHolder( data.entityKey ); if ( holder != null && holder.getEntity() != null && holder.isEventuallyInitialized() ) { return holder.getEntity(); } - // we need to register a resolution listener only if there is not an already initialized instance - // or an instance that another initializer is loading - registerResolutionListener( data ); - return null; + else { + // we need to register a resolution listener only if there is not an already initialized instance + // or an instance that another initializer is loading + registerResolutionListener( data ); + return null; + } } protected void registerToBatchFetchQueue(Data data) { @@ -238,7 +241,7 @@ public void initializeInstanceFromParent(Object parentInstance, Data data) { data.setState( State.MISSING ); } else { - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( instance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); if ( lazyInitializer != null && lazyInitializer.isUninitialized() ) { data.entityKey = new EntityKey( lazyInitializer.getInternalIdentifier(), concreteDescriptor ); registerToBatchFetchQueue( data ); @@ -259,40 +262,35 @@ protected static Object loadInstance( toOneMapping.isInternalLoadNullable() ); if ( instance == null ) { - if ( toOneMapping.getNotFoundAction() != NotFoundAction.IGNORE ) { - if ( affectedByFilter ) { - throw new EntityFilterException( - entityKey.getEntityName(), - entityKey.getIdentifier(), - toOneMapping.getNavigableRole().getFullPath() - ); - } - if ( toOneMapping.getNotFoundAction() == NotFoundAction.EXCEPTION ) { - throw new FetchNotFoundException( entityKey.getEntityName(), entityKey.getIdentifier() ); - } - } + handleNotFound( entityKey, toOneMapping, affectedByFilter ); } return instance; } + private static void handleNotFound(EntityKey entityKey, ToOneAttributeMapping toOneMapping, boolean affectedByFilter) { + final NotFoundAction notFoundAction = toOneMapping.getNotFoundAction(); // can be null + if ( affectedByFilter ) { + if ( notFoundAction != NotFoundAction.IGNORE ) { + throw new EntityFilterException( entityKey.getEntityName(), entityKey.getIdentifier(), + toOneMapping.getNavigableRole().getFullPath() ); + } + } + else { + if ( notFoundAction == NotFoundAction.EXCEPTION ) { + throw new FetchNotFoundException( entityKey.getEntityName(), entityKey.getIdentifier() ); + } + } + } + protected AttributeMapping[] getParentEntityAttributes(String attributeName) { final EntityPersister entityDescriptor = owningEntityInitializer.getEntityDescriptor(); - final AttributeMapping[] parentEntityAttributes = new AttributeMapping[ - entityDescriptor.getRootEntityDescriptor() - .getSubclassEntityNames() - .size() - ]; - parentEntityAttributes[entityDescriptor.getSubclassId()] = getParentEntityAttribute( - entityDescriptor, - toOneMapping, - attributeName - ); - for ( EntityMappingType subMappingType : entityDescriptor.getSubMappingTypes() ) { - parentEntityAttributes[subMappingType.getSubclassId()] = getParentEntityAttribute( - subMappingType, - toOneMapping, - attributeName - ); + final int size = entityDescriptor.getRootEntityDescriptor().getSubclassEntityNames().size(); + final AttributeMapping[] parentEntityAttributes = new AttributeMapping[size]; + parentEntityAttributes[entityDescriptor.getSubclassId()] = + getParentEntityAttribute( entityDescriptor, toOneMapping, attributeName ); + for ( var subMappingType : entityDescriptor.getSubMappingTypes() ) { + parentEntityAttributes[subMappingType.getSubclassId()] = + getParentEntityAttribute( subMappingType, toOneMapping, attributeName ); } return parentEntityAttributes; } @@ -302,8 +300,9 @@ protected static AttributeMapping getParentEntityAttribute( ToOneAttributeMapping referencedModelPart, String attributeName) { final AttributeMapping parentAttribute = subMappingType.findAttributeMapping( attributeName ); - if ( parentAttribute != null && parentAttribute.getDeclaringType() == referencedModelPart.getDeclaringType() - .findContainingEntityMapping() ) { + if ( parentAttribute != null + && parentAttribute.getDeclaringType() + == referencedModelPart.getDeclaringType().findContainingEntityMapping() ) { // These checks are needed to avoid setting the instance using the wrong (child's) model part or // setting it multiple times in case parent and child share the same attribute name for the association. return parentAttribute; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java index 773651c50370..afcae0379731 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java @@ -8,14 +8,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; @@ -31,7 +26,10 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.Type; -public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { +import static org.hibernate.internal.log.LoggingHelper.toLoggableString; + +public class BatchEntityInsideEmbeddableSelectFetchInitializer + extends AbstractBatchEntitySelectFetchInitializer { protected final Setter referencedModelPartSetter; protected final AttributeMapping[] rootEmbeddableAttributes; protected final Getter[] rootEmbeddableGetters; @@ -52,7 +50,8 @@ public Object readResolve() { } }; - public static class BatchEntityInsideEmbeddableSelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData { + public static class BatchEntityInsideEmbeddableSelectFetchInitializerData + extends AbstractBatchEntitySelectFetchInitializerData { private HashMap> toBatchLoad; public BatchEntityInsideEmbeddableSelectFetchInitializerData( @@ -125,12 +124,12 @@ public void initializeInstance(BatchEntityInsideEmbeddableSelectFetchInitializer super.initializeInstance( data ); // todo: check why this can't be moved to #registerToBatchFetchQueue if ( data.getInstance() == BATCH_PROPERTY ) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final InitializerData owningData = owningEntityInitializer.getData( rowProcessingState ); final int owningEntitySubclassId = owningEntityInitializer.getConcreteDescriptor( owningData ).getSubclassId(); final AttributeMapping rootEmbeddableAttribute = rootEmbeddableAttributes[owningEntitySubclassId]; if ( rootEmbeddableAttribute != null ) { - HashMap> toBatchLoad = data.toBatchLoad; + var toBatchLoad = data.toBatchLoad; if ( toBatchLoad == null ) { toBatchLoad = data.toBatchLoad = new HashMap<>(); } @@ -171,14 +170,14 @@ public ParentInfo( @Override public void endLoading(BatchEntityInsideEmbeddableSelectFetchInitializerData data) { super.endLoading( data ); - final HashMap> toBatchLoad = data.toBatchLoad; + final var toBatchLoad = data.toBatchLoad; if ( toBatchLoad != null ) { - for ( Map.Entry> entry : toBatchLoad.entrySet() ) { + for ( var entry : toBatchLoad.entrySet() ) { final EntityKey entityKey = entry.getKey(); final List parentInfos = entry.getValue(); - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); - final SessionFactoryImplementor factory = session.getFactory(); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final var session = data.getRowProcessingState().getSession(); + final var factory = session.getFactory(); + final var persistenceContext = session.getPersistenceContextInternal(); final Object loadedInstance = loadInstance( entityKey, toOneMapping, affectedByFilter, session ); for ( ParentInfo parentInfo : parentInfos ) { final Object parentEntityInstance = parentInfo.parentEntityInstance; @@ -194,11 +193,11 @@ public void endLoading(BatchEntityInsideEmbeddableSelectFetchInitializerData dat The value of RootEmbeddable is needed to update the ParentEntity loaded state */ final int parentEntitySubclassId = parentInfo.parentEntitySubclassId; - final Object rootEmbeddable = rootEmbeddableGetters[parentEntitySubclassId].get( parentEntityInstance ); - loadedState[parentInfo.propertyIndex] = rootEmbeddablePropertyTypes[parentEntitySubclassId].deepCopy( - rootEmbeddable, - factory - ); + final Object rootEmbeddable = + rootEmbeddableGetters[parentEntitySubclassId].get( parentEntityInstance ); + loadedState[parentInfo.propertyIndex] = + rootEmbeddablePropertyTypes[parentEntitySubclassId] + .deepCopy( rootEmbeddable, factory ); } } } @@ -223,7 +222,7 @@ protected static String getRootEmbeddablePropertyName( @Override public String toString() { - return "BatchEntityInsideEmbeddableSelectFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; + return "BatchEntityInsideEmbeddableSelectFetchInitializer(" + toLoggableString( getNavigablePath() ) + ")"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java index 12e5a2e557ff..5282b7af988b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java @@ -7,13 +7,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; @@ -26,12 +22,16 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.Type; -public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { +import static org.hibernate.internal.log.LoggingHelper.toLoggableString; + +public class BatchEntitySelectFetchInitializer + extends AbstractBatchEntitySelectFetchInitializer { protected final AttributeMapping[] parentAttributes; protected final Setter referencedModelPartSetter; protected final Type referencedModelPartType; - public static class BatchEntitySelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData { + public static class BatchEntitySelectFetchInitializerData + extends AbstractBatchEntitySelectFetchInitializerData { private HashMap> toBatchLoad; public BatchEntitySelectFetchInitializerData( @@ -63,8 +63,9 @@ protected InitializerData createInitializerData(RowProcessingState rowProcessing @Override protected void registerResolutionListener(BatchEntitySelectFetchInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final InitializerData owningData = owningEntityInitializer.getData( rowProcessingState );HashMap> toBatchLoad = data.toBatchLoad; + final var rowProcessingState = data.getRowProcessingState(); + final InitializerData owningData = owningEntityInitializer.getData( rowProcessingState ); + var toBatchLoad = data.toBatchLoad; if ( toBatchLoad == null ) { toBatchLoad = data.toBatchLoad = new HashMap<>(); } @@ -96,11 +97,11 @@ public ParentInfo(Object parentInstance, int propertyIndex) { @Override public void endLoading(BatchEntitySelectFetchInitializerData data) { super.endLoading( data ); - final HashMap> toBatchLoad = data.toBatchLoad; + final var toBatchLoad = data.toBatchLoad; if ( toBatchLoad != null ) { - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - for ( Map.Entry> entry : toBatchLoad.entrySet() ) { + final var session = data.getRowProcessingState().getSession(); + final var persistenceContext = session.getPersistenceContextInternal(); + for ( var entry : toBatchLoad.entrySet() ) { final EntityKey entityKey = entry.getKey(); final List parentInfos = entry.getValue(); final Object instance = loadInstance( entityKey, toOneMapping, affectedByFilter, session ); @@ -110,10 +111,8 @@ public void endLoading(BatchEntitySelectFetchInitializerData data) { referencedModelPartSetter.set( parentInstance, instance ); final Object[] loadedState = entityEntry.getLoadedState(); if ( loadedState != null ) { - loadedState[parentInfo.propertyIndex] = referencedModelPartType.deepCopy( - instance, - session.getFactory() - ); + loadedState[parentInfo.propertyIndex] = + referencedModelPartType.deepCopy( instance, session.getFactory() ); } } } @@ -123,7 +122,7 @@ public void endLoading(BatchEntitySelectFetchInitializerData data) { @Override public String toString() { - return "BatchEntitySelectFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; + return "BatchEntitySelectFetchInitializer(" + toLoggableString( getNavigablePath() ) + ")"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java index dd8569529f25..15e192590677 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java @@ -7,7 +7,6 @@ import java.util.HashSet; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; @@ -24,7 +23,8 @@ */ public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { - public static class BatchInitializeEntitySelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData { + public static class BatchInitializeEntitySelectFetchInitializerData + extends AbstractBatchEntitySelectFetchInitializerData { private HashSet toBatchLoad; public BatchInitializeEntitySelectFetchInitializerData( @@ -65,7 +65,7 @@ protected void registerToBatchFetchQueue(BatchInitializeEntitySelectFetchInitial false, false ) ); - HashSet toBatchLoad = data.toBatchLoad; + var toBatchLoad = data.toBatchLoad; if ( toBatchLoad == null ) { toBatchLoad = data.toBatchLoad = new HashSet<>(); } @@ -75,9 +75,9 @@ protected void registerToBatchFetchQueue(BatchInitializeEntitySelectFetchInitial @Override public void endLoading(BatchInitializeEntitySelectFetchInitializerData data) { super.endLoading( data ); - final HashSet toBatchLoad = data.toBatchLoad; + final var toBatchLoad = data.toBatchLoad; if ( toBatchLoad != null ) { - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + final var session = data.getRowProcessingState().getSession(); for ( EntityKey key : toBatchLoad ) { loadInstance( key, toOneMapping, affectedByFilter, session ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java index ba21c6d7b458..3b9caea049c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java @@ -9,9 +9,6 @@ import org.hibernate.Hibernate; import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart; import org.hibernate.metamodel.mapping.ModelPart; @@ -30,6 +27,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; +import static org.hibernate.internal.log.LoggingHelper.toLoggableString; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** @@ -79,14 +77,10 @@ public DiscriminatedEntityInitializer( this.eager = eager; this.resultInitializer = resultInitializer; final Initializer initializer = keyValueAssembler.getInitializer(); - if ( initializer == null ) { - this.keyIsEager = false; - this.hasLazySubInitializer = false; - } - else { - this.keyIsEager = initializer.isEager(); - this.hasLazySubInitializer = !initializer.isEager() || initializer.hasLazySubInitializers(); - } + this.keyIsEager = initializer != null && initializer.isEager(); + this.hasLazySubInitializer = + initializer != null + && ( !initializer.isEager() || initializer.hasLazySubInitializers() ); } @Override @@ -116,7 +110,7 @@ public void resolveKey(DiscriminatedEntityInitializerData data) { // resolve the key and the discriminator, and then use those to load the indicated entity - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final Object discriminatorValue = discriminatorValueAssembler.assemble( rowProcessingState ); if ( discriminatorValue == null ) { @@ -136,7 +130,7 @@ public void resolveKey(DiscriminatedEntityInitializerData data) { @Override public void resolveState(DiscriminatedEntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); discriminatorValueAssembler.resolveState( rowProcessingState ); keyValueAssembler.resolveState( rowProcessingState ); } @@ -165,10 +159,10 @@ public void resolveInstance(DiscriminatedEntityInitializerData data) { data.setState( State.INITIALIZED ); - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + final var session = data.getRowProcessingState().getSession(); final EntityKey entityKey = new EntityKey( data.entityIdentifier, data.concreteDescriptor ); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final var persistenceContext = session.getPersistenceContextInternal(); final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); if ( holder != null ) { final Object instance = holder.getEntity(); @@ -207,12 +201,12 @@ public void resolveInstance(Object instance, DiscriminatedEntityInitializerData data.setInstance( null ); } else { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); if ( lazyInitializer == null ) { data.setState( State.INITIALIZED ); if ( keyIsEager ) { - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final var session = rowProcessingState.getSession(); data.concreteDescriptor = session.getEntityPersister( null, instance ); data.entityIdentifier = data.concreteDescriptor.getIdentifier( instance, session ); } @@ -331,7 +325,7 @@ public boolean isResultInitializer() { @Override public String toString() { - return "DiscriminatedEntityInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; + return "DiscriminatedEntityInitializer(" + toLoggableString( getNavigablePath() ) + ")"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java index 92441140cc40..871f4d905f8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java @@ -12,17 +12,12 @@ import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityUniqueKey; -import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistentAttributeInterceptable; -import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.AppliedGraph; -import org.hibernate.graph.spi.AttributeNodeImplementor; -import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; @@ -41,6 +36,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import static org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.UNFETCHED_PROPERTY; +import static org.hibernate.internal.log.LoggingHelper.toLoggableString; +import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; import static org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.determineConcreteEntityDescriptor; /** @@ -80,7 +77,8 @@ public EntityDelayedFetchInitializer( AssemblerCreationState creationState) { super( creationState ); // associations marked with `@NotFound` are ALWAYS eagerly fetched, unless we're resolving the concrete type - assert !referencedModelPart.hasNotFoundAction() || referencedModelPart.getEntityMappingType().isConcreteProxy(); + assert !referencedModelPart.hasNotFoundAction() + || referencedModelPart.getEntityMappingType().isConcreteProxy(); this.parent = parent; this.navigablePath = fetchedNavigable; @@ -88,18 +86,18 @@ public EntityDelayedFetchInitializer( this.referencedModelPart = referencedModelPart; this.selectByUniqueKey = selectByUniqueKey; this.identifierAssembler = keyResult.createResultAssembler( this, creationState ); - this.discriminatorAssembler = discriminatorResult == null - ? null - : (BasicResultAssembler) discriminatorResult.createResultAssembler( this, creationState ); - final Initializer initializer; - if ( identifierAssembler == null || ( initializer = identifierAssembler.getInitializer() ) == null ) { - this.keyIsEager = false; - this.hasLazySubInitializer = false; - } - else { - this.keyIsEager = initializer.isEager(); - this.hasLazySubInitializer = !initializer.isEager() || initializer.hasLazySubInitializers(); - } + this.discriminatorAssembler = + discriminatorResult == null + ? null + : (BasicResultAssembler) + discriminatorResult.createResultAssembler( this, creationState ); + final Initializer initializer = + identifierAssembler == null ? null + : identifierAssembler.getInitializer(); + this.keyIsEager = initializer != null && initializer.isEager(); + this.hasLazySubInitializer = + initializer != null + && ( !initializer.isEager() || initializer.hasLazySubInitializers() ); } @Override @@ -142,7 +140,7 @@ public void resolveInstance(EntityDelayedFetchInitializerData data) { // This initializer is done initializing, since this is only invoked for delayed or select initializers data.setState( State.INITIALIZED ); - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); data.entityIdentifier = identifierAssembler.assemble( rowProcessingState ); if ( data.entityIdentifier == null ) { @@ -150,7 +148,7 @@ public void resolveInstance(EntityDelayedFetchInitializerData data) { data.setState( State.MISSING ); } else { - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final var session = rowProcessingState.getSession(); final EntityPersister entityPersister = getEntityDescriptor(); final EntityPersister concreteDescriptor; @@ -174,7 +172,7 @@ public void resolveInstance(EntityDelayedFetchInitializerData data) { concreteDescriptor = entityPersister; } - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final var persistenceContext = session.getPersistenceContextInternal(); if ( selectByUniqueKey ) { final String uniqueKeyPropertyName = referencedModelPart.getReferencedPropertyName(); final Type uniqueKeyPropertyType = ( referencedModelPart.getReferencedPropertyName() == null ) ? @@ -222,8 +220,8 @@ public void resolveInstance(EntityDelayedFetchInitializerData data) { session ); - // If the entity was not in the Persistence Context, but was found now, - // add it to the Persistence Context + // If the entity was not in the persistence context + // but was found now, add it to the persistence context if ( instance != null ) { persistenceContext.addEntity( euk, instance ); } @@ -242,7 +240,7 @@ public void resolveInstance(EntityDelayedFetchInitializerData data) { if ( holder != null && holder.getEntity() != null ) { instance = persistenceContext.proxyFor( holder, concreteDescriptor ); } - // For primary key based mappings we only use bytecode-laziness if the attribute is optional, + // For primary key-based mappings we only use bytecode-laziness if the attribute is optional, // because the non-optionality implies that it is safe to have a proxy else if ( referencedModelPart.isOptional() && referencedModelPart.isLazy() ) { instance = UNFETCHED_PROPERTY; @@ -255,7 +253,7 @@ else if ( referencedModelPart.isOptional() && referencedModelPart.isLazy() ) { false ); - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( instance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); if ( lazyInitializer != null ) { lazyInitializer.setUnwrap( referencedModelPart.isUnwrapProxy() && concreteDescriptor.isInstrumented() ); } @@ -268,8 +266,7 @@ else if ( referencedModelPart.isOptional() && referencedModelPart.isLazy() ) { private boolean isLazyByGraph(RowProcessingState rowProcessingState) { final AppliedGraph appliedGraph = rowProcessingState.getQueryOptions().getAppliedGraph(); if ( appliedGraph != null && appliedGraph.getSemantic() == GraphSemantic.FETCH ) { - final AttributeNodeImplementor attributeNode = - appliedGraph.getGraph().findAttributeNode( navigablePath.getLocalName() ); + final var attributeNode = appliedGraph.getGraph().findAttributeNode( navigablePath.getLocalName() ); return attributeNode == null || attributeNode.getAttributeDescriptor() != getInitializedPart().asAttributeMapping(); } @@ -287,7 +284,7 @@ public void resolveInstance(Object instance, EntityDelayedFetchInitializerData d // This initializer is done initializing, since this is only invoked for delayed or select initializers data.setState( State.INITIALIZED ); data.setInstance( instance ); - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); if ( keyIsEager ) { data.entityIdentifier = getEntityDescriptor().getIdentifier( instance, rowProcessingState.getSession() ); final Initializer initializer = identifierAssembler.getInitializer(); @@ -360,7 +357,7 @@ public void resolveState(EntityDelayedFetchInitializerData data) { @Override public String toString() { - return "EntityDelayedFetchInitializer(" + LoggingHelper.toLoggableString( navigablePath ) + ")"; + return "EntityDelayedFetchInitializer(" + toLoggableString( navigablePath ) + ")"; } //######################### diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java index 84b19926bb2b..b3fc8126d974 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java @@ -6,7 +6,6 @@ import java.util.Arrays; import java.util.BitSet; -import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; @@ -30,8 +29,6 @@ import org.hibernate.engine.spi.EntityUniqueKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistentAttributeInterceptor; -import org.hibernate.engine.spi.SessionEventListenerManager; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.event.monitor.spi.EventMonitor; @@ -43,8 +40,6 @@ import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMetadata; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; -import org.hibernate.metamodel.mapping.DiscriminatorValueDetails; -import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityVersionMapping; @@ -228,9 +223,10 @@ public EntityInitializerImpl( entityDescriptor = (EntityPersister) referencedModelPart.getEntityMappingType(); final String rootEntityName = entityDescriptor.getRootEntityName(); - rootEntityDescriptor = rootEntityName == null || rootEntityName.equals( entityDescriptor.getEntityName() ) - ? entityDescriptor - : entityDescriptor.getRootEntityDescriptor().getEntityPersister(); + rootEntityDescriptor = + rootEntityName == null || rootEntityName.equals( entityDescriptor.getEntityName() ) + ? entityDescriptor + : entityDescriptor.getRootEntityDescriptor().getEntityPersister(); keyTypeForEqualsHashCode = entityDescriptor.getIdentifierType().getTypeForEqualsHashCode(); // The id can only be the entity instance if this is a non-aggregated id that has no containing class couldUseEmbeddedIdentifierInstanceAsEntity = @@ -285,7 +281,7 @@ public EntityInitializerImpl( : null; final int fetchableCount = entityDescriptor.getNumberOfFetchables(); - final Collection subMappingTypes = rootEntityDescriptor.getSubMappingTypes(); + final var subMappingTypes = rootEntityDescriptor.getSubMappingTypes(); final DomainResultAssembler[][] assemblers = new DomainResultAssembler[subMappingTypes.size() + 1][]; final Initializer[] allInitializers = new Initializer[fetchableCount]; final Initializer[][] subInitializers = new Initializer[subMappingTypes.size() + 1][]; @@ -300,9 +296,10 @@ public EntityInitializerImpl( new MutabilityPlan[rootEntityDescriptor.getNumberOfAttributeMappings()]; for ( EntityMappingType subMappingType : subMappingTypes ) { - assemblers[subMappingType.getSubclassId()] = + final int subclassId = subMappingType.getSubclassId(); + assemblers[subclassId] = new DomainResultAssembler[subMappingType.getNumberOfFetchables()]; - updatableAttributeMutabilityPlans[subMappingType.getSubclassId()] = + updatableAttributeMutabilityPlans[subclassId] = new MutabilityPlan[subMappingType.getNumberOfAttributeMappings()]; } @@ -355,28 +352,29 @@ public EntityInitializerImpl( if ( attributeMetadata.isUpdatable() ) { updatableAttributeMutabilityPlans[subclassId][stateArrayPosition] = attributeMetadata.getMutabilityPlan(); } - for ( EntityMappingType subMappingType : declaringType.getSubMappingTypes() ) { - assemblers[subMappingType.getSubclassId()][stateArrayPosition] = stateAssembler; - updatableAttributeMutabilityPlans[subMappingType.getSubclassId()][stateArrayPosition] = + for ( var subMappingType : declaringType.getSubMappingTypes() ) { + final int subclassMappingId = subMappingType.getSubclassId(); + assemblers[subclassMappingId][stateArrayPosition] = stateAssembler; + updatableAttributeMutabilityPlans[subclassMappingId][stateArrayPosition] = updatableAttributeMutabilityPlans[subclassId][stateArrayPosition]; if ( subInitializer != null ) { - if ( subInitializers[subMappingType.getSubclassId()] == null ) { - subInitializers[subMappingType.getSubclassId()] = new Initializer[fetchableCount]; - eagerSubInitializers[subMappingType.getSubclassId()] = new Initializer[fetchableCount]; - collectionContainingSubInitializers[subMappingType.getSubclassId()] = new Initializer[fetchableCount]; - lazySets[subMappingType.getSubclassId()] = new BitSet(fetchableCount); - maybeLazySets[subMappingType.getSubclassId()] = new BitSet(fetchableCount); + if ( subInitializers[subclassMappingId] == null ) { + subInitializers[subclassMappingId] = new Initializer[fetchableCount]; + eagerSubInitializers[subclassMappingId] = new Initializer[fetchableCount]; + collectionContainingSubInitializers[subclassMappingId] = new Initializer[fetchableCount]; + lazySets[subclassMappingId] = new BitSet(fetchableCount); + maybeLazySets[subclassMappingId] = new BitSet(fetchableCount); } - subInitializers[subMappingType.getSubclassId()][stateArrayPosition] = subInitializer; - eagerSubInitializers[subMappingType.getSubclassId()][stateArrayPosition] = + subInitializers[subclassMappingId][stateArrayPosition] = subInitializer; + eagerSubInitializers[subclassMappingId][stateArrayPosition] = eagerSubInitializers[subclassId][stateArrayPosition]; - collectionContainingSubInitializers[subMappingType.getSubclassId()][stateArrayPosition] = + collectionContainingSubInitializers[subclassMappingId][stateArrayPosition] = collectionContainingSubInitializers[subclassId][stateArrayPosition]; if ( lazySets[subclassId].get( stateArrayPosition ) ) { - lazySets[subMappingType.getSubclassId()].set( stateArrayPosition ); + lazySets[subclassMappingId].set( stateArrayPosition ); } if ( maybeLazySets[subclassId].get( stateArrayPosition ) ) { - maybeLazySets[subMappingType.getSubclassId()].set( stateArrayPosition ); + maybeLazySets[subclassMappingId].set( stateArrayPosition ); } } } @@ -540,7 +538,7 @@ protected void resolveKey(EntityInitializerData data, boolean entityKeyOnly) { data.entityInstanceForNotify = null; data.entityHolder = null; - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final Object id; if ( identifierAssembler == null ) { id = rowProcessingState.getEntityId(); @@ -548,8 +546,7 @@ protected void resolveKey(EntityInitializerData data, boolean entityKeyOnly) { } else { //noinspection unchecked - final Initializer initializer = - (Initializer) identifierAssembler.getInitializer(); + final var initializer = (Initializer) identifierAssembler.getInitializer(); if ( initializer != null ) { final InitializerData subData = initializer.getData( rowProcessingState ); initializer.resolveKey( subData ); @@ -622,7 +619,9 @@ && areKeysEqual( oldEntityKey.getIdentifier(), id ) && !oldEntityHolder.isDetach } private boolean areKeysEqual(Object key1, Object key2) { - return keyTypeForEqualsHashCode == null ? key1.equals( key2 ) : keyTypeForEqualsHashCode.isEqual( key1, key2 ); + return keyTypeForEqualsHashCode == null + ? key1.equals( key2 ) + : keyTypeForEqualsHashCode.isEqual( key1, key2 ); } protected void resolveInstanceSubInitializers(EntityInitializerData data) { @@ -646,9 +645,8 @@ protected void resolveInstanceSubInitializers(EntityInitializerData data) { return; } } - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final PersistenceContext persistenceContext = rowProcessingState.getSession() - .getPersistenceContextInternal(); + final var rowProcessingState = data.getRowProcessingState(); + final var persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal(); assert entityEntry == persistenceContext.getEntry( data.entityInstanceForNotify ); final Object[] loadedState = entityEntry.getLoadedState(); final Object[] state; @@ -684,18 +682,19 @@ protected void resolveInstanceSubInitializers(EntityInitializerData data) { private void notifySubInitializersToReusePreviousRowInstance(EntityInitializerData data) { final EntityEntry entityEntry = data.entityHolder.getEntityEntry(); - final Initializer[] subInitializer; - final ImmutableBitSet maybeLazySet; - if ( data.entityHolder.getEntityInitializer() == this ) { - // When a previous row initialized this entity already, we only need to process collections - subInitializer = collectionContainingSubInitializers[data.concreteDescriptor.getSubclassId()]; - maybeLazySet = null; - } - else { - subInitializer = subInitializersForResolveFromInitialized[data.concreteDescriptor.getSubclassId()]; - maybeLazySet = entityEntry == null ? null : entityEntry.getMaybeLazySet(); - } - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final int subclassId = data.concreteDescriptor.getSubclassId(); + // When a previous row initialized this entity already, we only need to process collections + final boolean sameInitializerAsPreviousRow = + data.entityHolder.getEntityInitializer() == this; + final Initializer[] subInitializer = + sameInitializerAsPreviousRow + ? collectionContainingSubInitializers[subclassId] + : subInitializersForResolveFromInitialized[subclassId]; + final ImmutableBitSet maybeLazySet = + sameInitializerAsPreviousRow || entityEntry == null + ? null + : entityEntry.getMaybeLazySet(); + final var rowProcessingState = data.getRowProcessingState(); for ( int i = 0; i < subInitializer.length; i++ ) { final Initializer initializer = subInitializer[i]; // It is vital to only resolveFromPreviousRow only for the initializers where the state is maybe lazy, @@ -707,8 +706,8 @@ private void notifySubInitializersToReusePreviousRowInstance(EntityInitializerDa } protected void resolveKeySubInitializers(EntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - for ( Initializer initializer : subInitializers[data.concreteDescriptor.getSubclassId()] ) { + final var rowProcessingState = data.getRowProcessingState(); + for ( var initializer : subInitializers[data.concreteDescriptor.getSubclassId()] ) { if ( initializer != null ) { initializer.resolveKey( rowProcessingState ); } @@ -745,17 +744,14 @@ protected void setMissing(EntityInitializerData data) { final Object fkKeyValue = keyAssembler.assemble( data.getRowProcessingState() ); if ( fkKeyValue != null ) { if ( notFoundAction != NotFoundAction.IGNORE ) { + final String entityName = getEntityDescriptor().getEntityName(); if ( affectedByFilter ) { - throw new EntityFilterException( - getEntityDescriptor().getEntityName(), - fkKeyValue, - referencedModelPart.getNavigableRole().getFullPath() - ); + throw new EntityFilterException( entityName, fkKeyValue, + referencedModelPart.getNavigableRole().getFullPath() ); + } + else { + throw new FetchNotFoundException( entityName, fkKeyValue ); } - throw new FetchNotFoundException( - getEntityDescriptor().getEntityName(), - fkKeyValue - ); } } } @@ -781,7 +777,7 @@ public void initializeInstanceFromParent(Object parentInstance, EntityInitialize final Object instance = attributeMapping != null ? attributeMapping.getValue( parentInstance ) : parentInstance; - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + final var session = data.getRowProcessingState().getSession(); if ( instance == null ) { setMissing( data ); } @@ -789,10 +785,8 @@ public void initializeInstanceFromParent(Object parentInstance, EntityInitialize data.setInstance( instance ); final Object entityInstanceForNotify = data.entityInstanceForNotify = Hibernate.unproxy( instance ); data.concreteDescriptor = session.getEntityPersister( null, entityInstanceForNotify ); - resolveEntityKey( - data, - data.concreteDescriptor.getIdentifier( entityInstanceForNotify, session ) - ); + resolveEntityKey( data, + data.concreteDescriptor.getIdentifier( entityInstanceForNotify, session ) ); data.entityHolder = session.getPersistenceContextInternal().getEntityHolder( data.entityKey ); data.setState( State.INITIALIZED ); initializeSubInstancesFromParent( data ); @@ -853,7 +847,7 @@ protected Type[] getParentEntityAttributeTypes(String attributeName) { if ( types == null ) { types = new Type[entityDescriptor.getRootEntityDescriptor().getSubclassEntityNames().size()]; initializeAttributeType( types, entityDescriptor, attributeName ); - for ( EntityMappingType subMappingType : entityDescriptor.getSubMappingTypes() ) { + for ( var subMappingType : entityDescriptor.getSubMappingTypes() ) { initializeAttributeType( types, subMappingType.getEntityPersister(), attributeName ); } parentEntityAttributeTypes.putIfAbsent( attributeName, types ); @@ -878,11 +872,10 @@ protected void initializeAttributeType(Type[] attributeTypes, EntityPersister en else { assert entityDescriptor.hasSubclasses() : "Reading a discriminator from a result set should only happen if the entity has subclasses"; - final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping(); + final var discriminatorMapping = entityDescriptor.getDiscriminatorMapping(); assert discriminatorMapping != null; final Object discriminator = discriminatorAssembler.extractRawValue( rowProcessingState ); - final DiscriminatorValueDetails discriminatorDetails = - discriminatorMapping.resolveDiscriminatorValue( discriminator ); + final var discriminatorDetails = discriminatorMapping.resolveDiscriminatorValue( discriminator ); if ( discriminatorDetails == null ) { assert discriminator == null : "Discriminator details should only be null for null values"; return null; @@ -925,9 +918,9 @@ public void resolveInstance(Object instance, EntityInitializerData data) { } data.setInstance( instance ); final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final var rowProcessingState = data.getRowProcessingState(); + final var session = rowProcessingState.getSession(); + final var persistenceContext = session.getPersistenceContextInternal(); if ( lazyInitializer == null ) { // Entity is most probably initialized data.entityInstanceForNotify = instance; @@ -1020,7 +1013,10 @@ public void resolveInstance(EntityInitializerData data) { if ( data.getState() != State.KEY_RESOLVED ) { return; } - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); + final var session = rowProcessingState.getSession(); + final var persistenceContext = session.getPersistenceContextInternal(); + data.setState( State.RESOLVED ); if ( data.entityKey == null ) { assert identifierAssembler != null; @@ -1032,13 +1028,12 @@ public void resolveInstance(EntityInitializerData data) { resolveEntityKey( data, id ); } data.entityHolder = - rowProcessingState.getSession().getPersistenceContextInternal() - .claimEntityHolderIfPossible( - data.entityKey, - null, - rowProcessingState.getJdbcValuesSourceProcessingState(), - this - ); + persistenceContext.claimEntityHolderIfPossible( + data.entityKey, + null, + rowProcessingState.getJdbcValuesSourceProcessingState(), + this + ); if ( useEmbeddedIdentifierInstanceAsEntity( data ) ) { data.setInstance( data.entityInstanceForNotify = rowProcessingState.getEntityId() ); @@ -1046,7 +1041,6 @@ public void resolveInstance(EntityInitializerData data) { else { resolveEntityInstance1( data ); if ( data.uniqueKeyAttributePath != null ) { - final SharedSessionContractImplementor session = rowProcessingState.getSession(); final EntityPersister concreteDescriptor = getConcreteDescriptor( data ); final EntityUniqueKey euk = new EntityUniqueKey( concreteDescriptor.getEntityName(), @@ -1055,7 +1049,7 @@ public void resolveInstance(EntityInitializerData data) { data.uniqueKeyPropertyTypes[concreteDescriptor.getSubclassId()], session.getFactory() ); - session.getPersistenceContextInternal().addEntity( euk, data.getInstance() ); + persistenceContext.addEntity( euk, data.getInstance() ); } } @@ -1080,9 +1074,9 @@ protected void resolveEntityInstance1(EntityInitializerData data) { && referencedModelPart instanceof ToOneAttributeMapping toOneAttributeMapping && toOneAttributeMapping.isUnwrapProxy() && getConcreteDescriptor( data ).getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); - final Object entityFromExecutionContext; if ( !unwrapProxy && isProxyInstance( proxy ) ) { - if ( ( entityFromExecutionContext = getEntityFromExecutionContext( data ) ) != null ) { + final Object entityFromExecutionContext = getEntityFromExecutionContext( data ); + if ( entityFromExecutionContext != null ) { data.setInstance( data.entityInstanceForNotify = entityFromExecutionContext ); // If the entity comes from the execution context, it is treated as not initialized // so that we can refresh the data as requested @@ -1119,27 +1113,30 @@ else if ( data.entityHolder.getEntityInitializer() != this ) { data.setState( State.INITIALIZED ); } } - else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( data ) ) != null ) { - // This is the entity to refresh, so don't set the state to initialized - data.setInstance( data.entityInstanceForNotify = entityFromExecutionContext ); - if ( isResultInitializer() ) { - registerLoadingEntity( data, entityFromExecutionContext ); - } - } else { - assert data.entityHolder.getEntityInitializer() == this; - // look to see if another initializer from a parent load context or an earlier - // initializer is already loading the entity - data.setInstance( data.entityInstanceForNotify = resolveEntityInstance2( data ) ); - final Initializer idInitializer; - if ( data.entityHolder.getEntityInitializer() == this && data.getState() != State.INITIALIZED - && identifierAssembler != null - && ( idInitializer = identifierAssembler.getInitializer() ) != null ) { - // If this is the owning initializer and the returned object is not initialized, - // this means that the entity instance was just instantiated. - // In this case, we want to call "assemble" and hence "initializeInstance" on the initializer - // for possibly non-aggregated identifier mappings, so inject the virtual id representation - idInitializer.initializeInstance( data.getRowProcessingState() ); + final Object entityFromExecutionContext = getEntityFromExecutionContext( data ); + if ( entityFromExecutionContext != null ) { + // This is the entity to refresh, so don't set the state to initialized + data.setInstance( data.entityInstanceForNotify = entityFromExecutionContext ); + if ( isResultInitializer() ) { + registerLoadingEntity( data, entityFromExecutionContext ); + } + } + else { + assert data.entityHolder.getEntityInitializer() == this; + // look to see if another initializer from a parent load context or an earlier + // initializer is already loading the entity + data.setInstance( data.entityInstanceForNotify = resolveEntityInstance2( data ) ); + final Initializer idInitializer; + if ( data.entityHolder.getEntityInitializer() == this && data.getState() != State.INITIALIZED + && identifierAssembler != null + && (idInitializer = identifierAssembler.getInitializer()) != null ) { + // If this is the owning initializer and the returned object is not initialized, + // this means that the entity instance was just instantiated. + // In this case, we want to call "assemble" and hence "initializeInstance" on the initializer + // for possibly non-aggregated identifier mappings, so inject the virtual id representation + idInitializer.initializeInstance( data.getRowProcessingState() ); + } } } } @@ -1148,9 +1145,10 @@ else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( data ) ) } protected Object getEntityFromExecutionContext(EntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final ExecutionContext executionContext = rowProcessingState.getJdbcValuesSourceProcessingState() - .getExecutionContext(); + final var rowProcessingState = data.getRowProcessingState(); + final ExecutionContext executionContext = + rowProcessingState.getJdbcValuesSourceProcessingState() + .getExecutionContext(); if ( rootEntityDescriptor == executionContext.getRootEntityDescriptor() && areKeysEqual( data.entityKey.getIdentifier(), executionContext.getEntityId() ) ) { return executionContext.getEntityInstance(); @@ -1159,7 +1157,7 @@ && areKeysEqual( data.entityKey.getIdentifier(), executionContext.getEntityId() } protected void upgradeLockMode(EntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); if ( data.lockMode != LockMode.NONE && rowProcessingState.upgradeLocks() ) { final EntityEntry entry = data.entityHolder.getEntityEntry(); assert entry == rowProcessingState.getSession().getPersistenceContextInternal() @@ -1177,7 +1175,8 @@ protected void upgradeLockMode(EntityInitializerData data) { private boolean isProxyInstance(Object proxy) { return proxy != null - && ( proxy instanceof MapProxy || entityDescriptor.getJavaType().getJavaTypeClass().isInstance( proxy ) ); + && ( proxy instanceof MapProxy + || entityDescriptor.getJavaType().getJavaTypeClass().isInstance( proxy ) ); } private boolean isExistingEntityInitialized(Object existingEntity) { @@ -1198,7 +1197,8 @@ private void checkVersion( // null version means the object is in the process of being loaded somewhere else in the ResultSet final Object currentVersion = versionAssembler.assemble( rowProcessingState ); if ( !data.concreteDescriptor.getVersionType().isEqual( version, currentVersion ) ) { - final StatisticsImplementor statistics = rowProcessingState.getSession().getFactory().getStatistics(); + final StatisticsImplementor statistics = + rowProcessingState.getSession().getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.optimisticFailure( data.concreteDescriptor.getEntityName() ); } @@ -1224,7 +1224,7 @@ protected Object resolveEntityInstance2(EntityInitializerData data) { } protected Object resolveEntityInstance(EntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final Object resolved = resolveToOptionalInstance( data ); if ( resolved != null ) { registerLoadingEntity( data, resolved ); @@ -1234,11 +1234,12 @@ protected Object resolveEntityInstance(EntityInitializerData data) { if ( rowProcessingState.isQueryCacheHit() && entityDescriptor.useShallowQueryCacheLayout() ) { // We must load the entity this way, because the query cache entry contains only the primary key data.setState( State.INITIALIZED ); - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final var session = rowProcessingState.getSession(); assert data.entityHolder.getEntityInitializer() == this; // If this initializer owns the entity, we have to remove the entity holder, // because the subsequent loading process will claim the entity - rowProcessingState.getJdbcValuesSourceProcessingState().getLoadingEntityHolders().remove( data.entityHolder ); + rowProcessingState.getJdbcValuesSourceProcessingState() + .getLoadingEntityHolders().remove( data.entityHolder ); session.getPersistenceContextInternal().removeEntityHolder( data.entityKey ); return session.internalLoad( data.concreteDescriptor.getEntityName(), @@ -1303,13 +1304,14 @@ private Object resolveInstanceFromCache(EntityInitializerData data) { } protected void registerLoadingEntity(EntityInitializerData data, Object instance) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - rowProcessingState.getSession().getPersistenceContextInternal().claimEntityHolderIfPossible( - data.entityKey, - instance, - rowProcessingState.getJdbcValuesSourceProcessingState(), - this - ); + final var rowProcessingState = data.getRowProcessingState(); + rowProcessingState.getSession().getPersistenceContextInternal() + .claimEntityHolderIfPossible( + data.entityKey, + instance, + rowProcessingState.getJdbcValuesSourceProcessingState(), + this + ); } protected void registerReloadedEntity(EntityInitializerData data) { @@ -1331,17 +1333,18 @@ public void initializeInstance(EntityInitializerData data) { } protected boolean consistentInstance(EntityInitializerData data) { - final PersistenceContext persistenceContextInternal = - data.getRowProcessingState().getSession().getPersistenceContextInternal(); + final var persistenceContextInternal = + data.getRowProcessingState().getSession() + .getPersistenceContextInternal(); // Only call PersistenceContext#getEntity within the assert expression, as it is costly final Object entity = persistenceContextInternal.getEntity( data.entityKey ); return entity == null || entity == data.entityInstanceForNotify; } protected void initializeEntityInstance(EntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final var rowProcessingState = data.getRowProcessingState(); + final var session = rowProcessingState.getSession(); + final var persistenceContext = session.getPersistenceContextInternal(); final EntityKey entityKey = data.entityKey; assert entityKey != null; @@ -1352,7 +1355,7 @@ protected void initializeEntityInstance(EntityInitializerData data) { final Object entityInstanceForNotify = data.entityInstanceForNotify; if ( isPersistentAttributeInterceptable( entityInstanceForNotify ) ) { - final PersistentAttributeInterceptor persistentAttributeInterceptor = + final var persistentAttributeInterceptor = asPersistentAttributeInterceptable( entityInstanceForNotify ).$$_hibernate_getInterceptor(); if ( persistentAttributeInterceptor == null || persistentAttributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) { @@ -1445,7 +1448,8 @@ protected void registerNaturalIdResolution( Object[] resolvedEntityState) { if ( entityDescriptor.getNaturalIdMapping() != null ) { final Object naturalId = - entityDescriptor.getNaturalIdMapping().extractNaturalIdFromEntityState( resolvedEntityState ); + entityDescriptor.getNaturalIdMapping() + .extractNaturalIdFromEntityState( resolvedEntityState ); persistenceContext.getNaturalIdResolutions() .cacheResolutionFromLoad( data.entityKey.getIdentifier(), naturalId, entityDescriptor ); } @@ -1495,7 +1499,7 @@ private void putInCache( Object[] resolvedEntityState, Object version, EntityDataAccess cacheAccess) { - final SessionFactoryImplementor factory = session.getFactory(); + final var factory = session.getFactory(); final CacheEntry cacheEntry = data.concreteDescriptor.buildCacheEntry( data.entityInstanceForNotify, @@ -1551,7 +1555,7 @@ private void putInCache( } } else { - final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); + final var eventListenerManager = session.getEventListenerManager(); boolean put = false; final DiagnosticEvent cachePutEvent = eventMonitor.beginCachePutEvent(); try { @@ -1587,6 +1591,7 @@ protected void registerPossibleUniqueKeyEntries( EntityInitializerData data, Object[] resolvedEntityState, final SharedSessionContractImplementor session) { + final var persistenceContext = session.getPersistenceContextInternal(); for ( UniqueKeyEntry entry : data.concreteDescriptor.uniqueKeyEntries() ) { final String ukName = entry.getUniqueKeyName(); final int index = entry.getStateArrayPosition(); @@ -1617,17 +1622,17 @@ protected void registerPossibleUniqueKeyEntries( type, session.getFactory() ); - session.getPersistenceContextInternal().addEntity( entityUniqueKey, data.entityInstanceForNotify ); + persistenceContext.addEntity( entityUniqueKey, data.entityInstanceForNotify ); } } } protected Object[] extractConcreteTypeStateValues(EntityInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final Object[] values = new Object[data.concreteDescriptor.getNumberOfAttributeMappings()]; - final DomainResultAssembler[] concreteAssemblers = assemblers[data.concreteDescriptor.getSubclassId()]; + final var concreteAssemblers = assemblers[data.concreteDescriptor.getSubclassId()]; for ( int i = 0; i < values.length; i++ ) { - final DomainResultAssembler assembler = concreteAssemblers[i]; + final var assembler = concreteAssemblers[i]; values[i] = assembler == null ? UNFETCHED_PROPERTY : assembler.assemble( rowProcessingState ); } return values; @@ -1669,8 +1674,8 @@ public void resolveState(EntityInitializerData data) { protected void resolveEntityState(EntityInitializerData data) { assert data.concreteDescriptor != null; - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - for ( final DomainResultAssembler assembler : assemblers[data.concreteDescriptor.getSubclassId()] ) { + final var rowProcessingState = data.getRowProcessingState(); + for ( final var assembler : assemblers[data.concreteDescriptor.getSubclassId()] ) { if ( assembler != null ) { assembler.resolveState( rowProcessingState ); } @@ -1681,7 +1686,7 @@ protected boolean skipInitialization(EntityInitializerData data) { if ( data.entityHolder.getEntityInitializer() != this ) { return true; } - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final EntityEntry entry = data.entityHolder.getEntityEntry(); assert entry == rowProcessingState.getSession().getPersistenceContextInternal().getEntry( data.entityInstanceForNotify ); if ( entry == null ) { @@ -1693,8 +1698,9 @@ else if ( entry.getStatus().isDeletedOrGone() ) { } else { if ( isPersistentAttributeInterceptable( data.entityInstanceForNotify ) ) { - final PersistentAttributeInterceptor interceptor = - asPersistentAttributeInterceptable( data.entityInstanceForNotify ).$$_hibernate_getInterceptor(); + final var interceptor = + asPersistentAttributeInterceptable( data.entityInstanceForNotify ) + .$$_hibernate_getInterceptor(); if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) { // Avoid loading the same entity proxy twice for the same result set: it could lead to errors, // because some code writes to its input (ID in hydrated state replaced by the loaded entity, in particular). @@ -1722,8 +1728,8 @@ private boolean isReadOnly(RowProcessingState rowProcessingState, SharedSessionC } protected void preLoad(EntityInitializerData data, Object[] resolvedEntityState) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final var rowProcessingState = data.getRowProcessingState(); + final var session = rowProcessingState.getSession(); if ( session.isEventSource() ) { final PreLoadEvent preLoadEvent = rowProcessingState.getJdbcValuesSourceProcessingState().getPreLoadEvent(); assert preLoadEvent != null; @@ -1779,7 +1785,7 @@ protected void initializeSubInstancesFromParent(EntityInitializerData data) { @Override protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); if ( keyAssembler != null ) { final Initializer initializer = keyAssembler.getInitializer(); if ( initializer != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java index 4034a824c4a9..c71607e6a0f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java @@ -4,13 +4,7 @@ */ package org.hibernate.sql.results.graph.entity.internal; -import org.hibernate.EntityFilterException; -import org.hibernate.FetchNotFoundException; -import org.hibernate.annotations.NotFoundAction; import org.hibernate.engine.spi.EntityUniqueKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; @@ -18,10 +12,13 @@ import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.InitializerParent; +import static org.hibernate.internal.log.LoggingHelper.toLoggableString; + /** * @author Andrea Boriero */ -public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchInitializer { +public class EntitySelectFetchByUniqueKeyInitializer + extends EntitySelectFetchInitializer { private final ToOneAttributeMapping fetchedAttribute; public EntitySelectFetchByUniqueKeyInitializer( @@ -37,20 +34,18 @@ public EntitySelectFetchByUniqueKeyInitializer( } @Override - protected void initialize(EntitySelectFetchInitializerData data) { - final String entityName = concreteDescriptor.getEntityName(); - final String uniqueKeyPropertyName = fetchedAttribute.getReferencedPropertyName(); - - final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + protected void initializeIfNecessary(EntitySelectFetchInitializerData data) { + final var session = data.getRowProcessingState().getSession(); + final var persistenceContext = session.getPersistenceContextInternal(); + final String uniqueKeyPropertyName = fetchedAttribute.getReferencedPropertyName(); final EntityUniqueKey euk = new EntityUniqueKey( - entityName, + concreteDescriptor.getEntityName(), uniqueKeyPropertyName, data.entityIdentifier, concreteDescriptor.getPropertyType( uniqueKeyPropertyName ), session.getFactory() ); - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); data.setInstance( persistenceContext.getEntity( euk ) ); if ( data.getInstance() == null ) { final Object instance = concreteDescriptor.loadByUniqueKey( @@ -61,21 +56,10 @@ protected void initialize(EntitySelectFetchInitializerData data) { data.setInstance( instance ); if ( instance == null ) { - if ( toOneMapping.getNotFoundAction() != NotFoundAction.IGNORE ) { - if ( affectedByFilter ) { - throw new EntityFilterException( - entityName, - data.entityIdentifier, - toOneMapping.getNavigableRole().getFullPath() - ); - } - if ( toOneMapping.getNotFoundAction() == NotFoundAction.EXCEPTION ) { - throw new FetchNotFoundException( entityName, data.entityIdentifier ); - } - } + handleNotFound( data ); } - // If the entity was not in the Persistence Context, but was found now, - // add it to the Persistence Context + // If the entity was not in the persistence context but + // was found now, then add it to the persistence context persistenceContext.addEntity( euk, instance ); } if ( data.getInstance() != null ) { @@ -85,6 +69,6 @@ protected void initialize(EntitySelectFetchInitializerData data) { @Override public String toString() { - return "EntitySelectFetchByUniqueKeyInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; + return "EntitySelectFetchByUniqueKeyInitializer(" + toLoggableString( getNavigablePath() ) + ")"; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java index b7fc9523439a..cc3adf7f1f00 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java @@ -12,14 +12,10 @@ import org.hibernate.annotations.NotFoundAction; import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; @@ -34,6 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; +import static org.hibernate.internal.log.LoggingHelper.toLoggableString; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** @@ -57,13 +54,14 @@ public static class EntitySelectFetchInitializerData extends InitializerData { // per-row state protected @Nullable Object entityIdentifier; - public EntitySelectFetchInitializerData(EntitySelectFetchInitializer initializer, RowProcessingState rowProcessingState) { + public EntitySelectFetchInitializerData(RowProcessingState rowProcessingState) { super( rowProcessingState ); } /* * Used by Hibernate Reactive */ + @SuppressWarnings( "unused" ) public EntitySelectFetchInitializerData(EntitySelectFetchInitializerData original) { super( original ); this.entityIdentifier = original.entityIdentifier; @@ -85,22 +83,19 @@ public EntitySelectFetchInitializer( this.isPartOfKey = Initializer.isPartOfKey( fetchedNavigable, parent ); this.concreteDescriptor = concreteDescriptor; this.keyAssembler = keyResult.createResultAssembler( this, creationState ); - this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); + this.isEnhancedForLazyLoading = + concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); this.affectedByFilter = affectedByFilter; final Initializer initializer = keyAssembler.getInitializer(); - if ( initializer == null ) { - this.keyIsEager = false; - this.hasLazySubInitializer = false; - } - else { - this.keyIsEager = initializer.isEager(); - this.hasLazySubInitializer = !initializer.isEager() || initializer.hasLazySubInitializers(); - } + this.keyIsEager = initializer != null && initializer.isEager(); + this.hasLazySubInitializer = + initializer != null + && ( !initializer.isEager() || initializer.hasLazySubInitializers() ); } @Override protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { - return new EntitySelectFetchInitializerData( this, rowProcessingState ); + return new EntitySelectFetchInitializerData( rowProcessingState ); } public ModelPart getInitializedPart(){ @@ -135,31 +130,28 @@ public void resolveFromPreviousRow(Data data) { @Override public void resolveInstance(Data data) { - if ( data.getState() != State.KEY_RESOLVED ) { - return; - } - - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - data.entityIdentifier = keyAssembler.assemble( rowProcessingState ); - - if ( data.entityIdentifier == null ) { - data.setState( State.MISSING ); - data.setInstance( null ); - return; + if ( data.getState() == State.KEY_RESOLVED ) { + data.entityIdentifier = keyAssembler.assemble( data.getRowProcessingState() ); + if ( data.entityIdentifier == null ) { + data.setState( State.MISSING ); + data.setInstance( null ); + } + else { + data.setState( State.INITIALIZED ); + initializeIfNecessary( data ); + } } - data.setState( State.INITIALIZED ); - initialize( data ); } @Override public void resolveInstance(Object instance, Data data) { if ( instance == null ) { - data.setState( State.MISSING ); + data.setState( State.MISSING ); data.entityIdentifier = null; data.setInstance( null ); } else { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final var rowProcessingState = data.getRowProcessingState(); final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); if ( lazyInitializer == null ) { data.setState( State.INITIALIZED ); @@ -167,14 +159,8 @@ public void resolveInstance(Object instance, Data data) { data.entityIdentifier = concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() ); } } - else if ( lazyInitializer.isUninitialized() ) { - data.setState( State.RESOLVED ); - if ( keyIsEager ) { - data.entityIdentifier = lazyInitializer.getInternalIdentifier(); - } - } else { - data.setState( State.INITIALIZED ); + data.setState( lazyInitializer.isUninitialized() ? State.RESOLVED : State.INITIALIZED ); if ( keyIsEager ) { data.entityIdentifier = lazyInitializer.getInternalIdentifier(); } @@ -194,45 +180,25 @@ else if ( rowProcessingState.needsResolveState() ) { @Override public void initializeInstance(Data data) { - if ( data.getState() != State.RESOLVED ) { - return; + if ( data.getState() == State.RESOLVED ) { + data.setState( State.INITIALIZED ); + Hibernate.initialize( data.getInstance() ); } - data.setState( State.INITIALIZED ); - Hibernate.initialize( data.getInstance() ); } - protected void initialize(EntitySelectFetchInitializerData data) { - final RowProcessingState rowProcessingState = data.getRowProcessingState(); - final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final EntityKey entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor ); - - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); - if ( holder != null ) { - data.setInstance( persistenceContext.proxyFor( holder, concreteDescriptor ) ); - if ( holder.getEntityInitializer() == null ) { - if ( data.getInstance() != null && Hibernate.isInitialized( data.getInstance() ) ) { - data.setState( State.INITIALIZED ); - return; - } - } - else if ( holder.getEntityInitializer() != this ) { - // the entity is already being loaded elsewhere - data.setState( State.INITIALIZED ); - return; - } - else if ( data.getInstance() == null ) { - // todo: maybe mark this as resolved instead? - assert holder.getProxy() == null : "How to handle this case?"; - data.setState( State.INITIALIZED ); - return; - } - } + protected void initializeIfNecessary(EntitySelectFetchInitializerData data) { + final boolean found = alreadyInitialized( data ); data.setState( State.INITIALIZED ); - final String entityName = concreteDescriptor.getEntityName(); + if ( !found ) { + initialize( data ); + } + } + private void initialize(EntitySelectFetchInitializerData data) { + final var rowProcessingState = data.getRowProcessingState(); + final var session = rowProcessingState.getSession(); final Object instance = session.internalLoad( - entityName, + concreteDescriptor.getEntityName(), data.entityIdentifier, true, toOneMapping.isInternalLoadNullable() @@ -240,19 +206,8 @@ else if ( data.getInstance() == null ) { data.setInstance( instance ); if ( instance == null ) { - if ( toOneMapping.getNotFoundAction() != NotFoundAction.IGNORE ) { - if ( affectedByFilter ) { - throw new EntityFilterException( - entityName, - data.entityIdentifier, - toOneMapping.getNavigableRole().getFullPath() - ); - } - if ( toOneMapping.getNotFoundAction() == NotFoundAction.EXCEPTION ) { - throw new FetchNotFoundException( entityName, data.entityIdentifier ); - } - } - persistenceContext.claimEntityHolderIfPossible( + handleNotFound( data ); + session.getPersistenceContextInternal().claimEntityHolderIfPossible( new EntityKey( data.entityIdentifier, concreteDescriptor ), instance, rowProcessingState.getJdbcValuesSourceProcessingState(), @@ -260,10 +215,54 @@ else if ( data.getInstance() == null ) { ); } - final boolean unwrapProxy = toOneMapping.isUnwrapProxy() && isEnhancedForLazyLoading; - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( data.getInstance() ); + final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); if ( lazyInitializer != null ) { - lazyInitializer.setUnwrap( unwrapProxy ); + lazyInitializer.setUnwrap( toOneMapping.isUnwrapProxy() && isEnhancedForLazyLoading ); + } + } + + void handleNotFound(EntitySelectFetchInitializerData data) { + final NotFoundAction notFoundAction = toOneMapping.getNotFoundAction(); // can be null + if ( affectedByFilter ) { + if ( notFoundAction != NotFoundAction.IGNORE ) { + throw new EntityFilterException( concreteDescriptor.getEntityName(), data.entityIdentifier, + toOneMapping.getNavigableRole().getFullPath() ); + } + } + else { + if ( notFoundAction == NotFoundAction.EXCEPTION ) { + throw new FetchNotFoundException( concreteDescriptor.getEntityName(), data.entityIdentifier ); + } + } + } + + private boolean alreadyInitialized(EntitySelectFetchInitializerData data) { + final var persistenceContext = + data.getRowProcessingState().getSession() + .getPersistenceContextInternal(); + final EntityHolder holder = + persistenceContext.getEntityHolder( new EntityKey( data.entityIdentifier, concreteDescriptor ) ); + if ( holder == null ) { + return false; + } + else { + data.setInstance( persistenceContext.proxyFor( holder, concreteDescriptor ) ); // note side effect + if ( holder.getEntityInitializer() == null ) { + return data.getInstance() != null + && Hibernate.isInitialized( data.getInstance() ); + } + else if ( holder.getEntityInitializer() != this ) { + // the entity is already being loaded elsewhere + return true; + } + else if ( data.getInstance() == null ) { + // todo: maybe mark this as resolved instead? + assert holder.getProxy() == null : "How to handle this case?"; + return true; + } + else { + return false; + } } } @@ -337,7 +336,7 @@ public boolean isResultInitializer() { @Override public String toString() { - return "EntitySelectFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; + return "EntitySelectFetchInitializer(" + toLoggableString( getNavigablePath() ) + ")"; } public DomainResultAssembler getKeyAssembler() {