HHH-15854 Improve CollectionInitializer and EntityDelayedFetchInitializer resolveInstance methods performance when the parent entity is initialized
This commit is contained in:
parent
312d7e11a6
commit
98957c3509
|
@ -21,6 +21,7 @@ import org.hibernate.sql.ast.tree.select.SelectStatement;
|
|||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer;
|
||||
|
||||
/**
|
||||
* Encapsulates details related to entities which contain sub-select-fetchable
|
||||
|
@ -180,7 +181,7 @@ public class SubselectFetch {
|
|||
}
|
||||
|
||||
private boolean shouldAddSubselectFetch(LoadingEntityEntry entry) {
|
||||
if ( entry.getEntityInitializer().isEntityResultInitializer() ) {
|
||||
if ( entry.getEntityInitializer() instanceof EntityResultInitializer ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ import static org.hibernate.sql.results.graph.collection.CollectionLoadingLogger
|
|||
* @implNote Mainly an intention contract wrt the immediacy of the fetch.
|
||||
*/
|
||||
public abstract class AbstractImmediateCollectionInitializer extends AbstractCollectionInitializer {
|
||||
private final LockMode lockMode;
|
||||
|
||||
// per-row state
|
||||
private LoadingCollectionEntryImpl responsibility;
|
||||
|
@ -61,7 +60,6 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
|
|||
DomainResultAssembler<?> collectionValueKeyResultAssembler) {
|
||||
super( collectionPath, collectionAttributeMapping, parentAccess, collectionKeyResultAssembler );
|
||||
this.collectionValueKeyResultAssembler = collectionValueKeyResultAssembler;
|
||||
this.lockMode = lockMode;
|
||||
}
|
||||
|
||||
protected abstract String getSimpleConcreteImplName();
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
|||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
||||
/**
|
||||
|
@ -29,6 +30,12 @@ public class DelayedCollectionInitializer extends AbstractCollectionInitializer
|
|||
|
||||
@Override
|
||||
public void resolveInstance(RowProcessingState rowProcessingState) {
|
||||
if ( parentAccess != null ) {
|
||||
final EntityInitializer parentEntityInitializer = parentAccess.findFirstEntityInitializer();
|
||||
if ( parentEntityInitializer != null && parentEntityInitializer.isInitialized() ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolveInstance( rowProcessingState, false );
|
||||
}
|
||||
|
||||
|
|
|
@ -143,12 +143,19 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
|
||||
@Override
|
||||
public FetchParentAccess findFirstEntityDescriptorAccess() {
|
||||
return getFetchParentAccess().findFirstEntityDescriptorAccess();
|
||||
if ( fetchParentAccess == null ) {
|
||||
return null;
|
||||
}
|
||||
return fetchParentAccess.findFirstEntityDescriptorAccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityInitializer findFirstEntityInitializer() {
|
||||
return findFirstEntityDescriptorAccess().findFirstEntityInitializer();
|
||||
final FetchParentAccess firstEntityDescriptorAccess = findFirstEntityDescriptorAccess();
|
||||
if ( firstEntityDescriptorAccess == null ) {
|
||||
return null;
|
||||
}
|
||||
return firstEntityDescriptorAccess.findFirstEntityInitializer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.metamodel.mapping.ManagedMappingType;
|
|||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.proxy.map.MapProxy;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
|
@ -51,6 +52,7 @@ import org.hibernate.sql.results.graph.DomainResult;
|
|||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResultAssembler;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer;
|
||||
import org.hibernate.sql.results.internal.NullValueAssembler;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
|
||||
|
@ -409,7 +411,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
final Object entityInstanceFromExecutionContext =
|
||||
rowProcessingState.getJdbcValuesSourceProcessingState().getExecutionContext().getEntityInstance();
|
||||
if ( isProxyInstance( proxy ) ) {
|
||||
if ( isEntityResultInitializer() && entityInstanceFromExecutionContext != null ) {
|
||||
if ( this instanceof EntityResultInitializer && entityInstanceFromExecutionContext != null ) {
|
||||
entityInstance = entityInstanceFromExecutionContext;
|
||||
registerLoadingEntity( rowProcessingState, entityInstance );
|
||||
}
|
||||
|
@ -421,8 +423,12 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
final Object existingEntity = persistenceContext.getEntity( entityKey );
|
||||
if ( existingEntity != null ) {
|
||||
entityInstance = existingEntity;
|
||||
if ( existingLoadingEntry == null && isExistingEntityInitialized( existingEntity ) ) {
|
||||
notifyResolutionListeners( entityInstance );
|
||||
this.isInitialized = true;
|
||||
}
|
||||
}
|
||||
else if ( isEntityResultInitializer() && entityInstanceFromExecutionContext != null ) {
|
||||
else if ( this instanceof EntityResultInitializer && entityInstanceFromExecutionContext != null ) {
|
||||
entityInstance = entityInstanceFromExecutionContext;
|
||||
registerLoadingEntity( rowProcessingState, entityInstance );
|
||||
}
|
||||
|
@ -457,6 +463,26 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
&& ( proxy instanceof MapProxy || entityDescriptor.getJavaType().getJavaTypeClass().isInstance( proxy ) );
|
||||
}
|
||||
|
||||
private boolean isExistingEntityInitialized(Object existingEntity) {
|
||||
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance );
|
||||
if ( lazyInitializer != null ) {
|
||||
if ( lazyInitializer.isUninitialized() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ( isPersistentAttributeInterceptable( existingEntity ) ) {
|
||||
final PersistentAttributeInterceptor persistentAttributeInterceptor = asPersistentAttributeInterceptable(
|
||||
entityInstance ).$$_hibernate_getInterceptor();
|
||||
if ( persistentAttributeInterceptor == null || persistentAttributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the version of the object in the {@code RowProcessingState} against
|
||||
* the object version in the session cache, throwing an exception
|
||||
|
@ -953,6 +979,11 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return isInitialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPersister getConcreteDescriptor() {
|
||||
return concreteDescriptor;
|
||||
|
|
|
@ -60,6 +60,9 @@ public interface EntityInitializer extends FetchParentAccess {
|
|||
return this;
|
||||
}
|
||||
|
||||
default boolean isInitialized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isEntityResultInitializer() {
|
||||
return false;
|
||||
|
|
|
@ -83,6 +83,11 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
return;
|
||||
}
|
||||
|
||||
final EntityInitializer parentEntityInitializer = getParentEntityInitializer( parentAccess );
|
||||
if ( parentEntityInitializer != null && parentEntityInitializer.isInitialized() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isAttributeAssignableToConcreteDescriptor( parentAccess, referencedModelPart ) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -115,7 +120,7 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
if ( referencedModelPart.isOptional()
|
||||
&& parentAccess != null
|
||||
&& !parentAccess.isEmbeddableInitializer()
|
||||
&& isEnhancedForLazyLoading( parentAccess ) ) {
|
||||
&& isEnhancedForLazyLoading( parentEntityInitializer ) ) {
|
||||
entityInstance = LazyPropertyInitializer.UNFETCHED_PROPERTY;
|
||||
}
|
||||
else {
|
||||
|
@ -141,7 +146,7 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
if ( entityInstance == null ) {
|
||||
if ( parentAccess != null
|
||||
&& !parentAccess.isEmbeddableInitializer()
|
||||
&& isEnhancedForLazyLoading( parentAccess ) ) {
|
||||
&& isEnhancedForLazyLoading( parentEntityInitializer ) ) {
|
||||
return;
|
||||
}
|
||||
entityInstance = ( (UniqueKeyLoadable) concreteDescriptor ).loadByUniqueKey(
|
||||
|
@ -180,8 +185,16 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isEnhancedForLazyLoading(FetchParentAccess parentAccess) {
|
||||
return parentAccess.findFirstEntityInitializer().getEntityDescriptor().getBytecodeEnhancementMetadata()
|
||||
private EntityInitializer getParentEntityInitializer(FetchParentAccess parentAccess) {
|
||||
if ( parentAccess != null ) {
|
||||
return parentAccess.findFirstEntityInitializer();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isEnhancedForLazyLoading(EntityInitializer parentEntityIntialiazer) {
|
||||
return parentEntityIntialiazer != null && parentEntityIntialiazer.getEntityDescriptor()
|
||||
.getBytecodeEnhancementMetadata()
|
||||
.isEnhancedForLazyLoading();
|
||||
}
|
||||
|
||||
|
@ -238,4 +251,9 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
|
|||
return "EntityDelayedFetchInitializer(" + LoggingHelper.toLoggableString( navigablePath ) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEntityResultInitializer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,8 +57,4 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
|
|||
return CONCRETE_NAME + "(" + getNavigablePath() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEntityResultInitializer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.function.BiConsumer;
|
|||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.EntityUniqueKey;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
|
|
Loading…
Reference in New Issue