Skip to content

Commit

Permalink
HHH-15854 Improve CollectionInitializer and EntityDelayedFetchInitial…
Browse files Browse the repository at this point in the history
…izer resolveInstance methods performance when the parent entity is initialized
  • Loading branch information
dreab8 committed Jan 4, 2023
1 parent f6354ff commit 2c81979
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 20 deletions.
Expand Up @@ -21,6 +21,7 @@
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
Expand Down Expand Up @@ -180,7 +181,7 @@ public void addKey(EntityKey key, LoadingEntityEntry entry) {
}

private boolean shouldAddSubselectFetch(LoadingEntityEntry entry) {
if ( entry.getEntityInitializer().isEntityResultInitializer() ) {
if ( entry.getEntityInitializer() instanceof EntityResultInitializer ) {
return true;
}

Expand Down
Expand Up @@ -36,7 +36,6 @@
* @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;
Expand All @@ -61,7 +60,6 @@ public AbstractImmediateCollectionInitializer(
DomainResultAssembler<?> collectionValueKeyResultAssembler) {
super( collectionPath, collectionAttributeMapping, parentAccess, collectionKeyResultAssembler );
this.collectionValueKeyResultAssembler = collectionValueKeyResultAssembler;
this.lockMode = lockMode;
}

protected abstract String getSimpleConcreteImplName();
Expand Down
Expand Up @@ -11,6 +11,7 @@
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;

/**
Expand All @@ -29,6 +30,12 @@ public DelayedCollectionInitializer(

@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( parentAccess != null ) {
final EntityInitializer parentEntityInitializer = parentAccess.findFirstEntityInitializer();
if ( parentEntityInitializer != null && parentEntityInitializer.isInitialized() ) {
return;
}
}
resolveInstance( rowProcessingState, false );
}

Expand Down
Expand Up @@ -135,12 +135,19 @@ public Object getCompositeInstance() {

@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
Expand Down
Expand Up @@ -432,9 +432,8 @@ public void resolveInstance(RowProcessingState rowProcessingState) {
return;
}

final SharedSessionContractImplementor session = rowProcessingState
.getJdbcValuesSourceProcessingState()
.getSession();
final JdbcValuesSourceProcessingState jdbcValuesSourceProcessingState = rowProcessingState.getJdbcValuesSourceProcessingState();
final SharedSessionContractImplementor session = jdbcValuesSourceProcessingState.getSession();

final PersistenceContext persistenceContext = session.getPersistenceContext();
// Special case map proxy to avoid stack overflows
Expand Down Expand Up @@ -465,7 +464,7 @@ public void resolveInstance(RowProcessingState rowProcessingState) {
.getEntityInstance();
if ( proxy != null && ( proxy instanceof MapProxy
|| entityDescriptor.getJavaType().getJavaTypeClass().isInstance( proxy ) ) ) {
if ( this.isEntityResultInitializer() && entityInstanceFromExecutionContext != null ) {
if ( this instanceof EntityResultInitializer && entityInstanceFromExecutionContext != null ) {
this.entityInstance = entityInstanceFromExecutionContext;
registerLoadingEntity( rowProcessingState, entityInstance );
}
Expand All @@ -477,8 +476,12 @@ public void resolveInstance(RowProcessingState rowProcessingState) {
final Object existingEntity = persistenceContext.getEntity( entityKey );
if ( existingEntity != null ) {
this.entityInstance = existingEntity;
if ( existingLoadingEntry == null && isExistingEntityInitialized( existingEntity ) ) {
notifyResolutionListeners( entityInstance );
this.isInitialized = true;
}
}
else if ( this.isEntityResultInitializer() && entityInstanceFromExecutionContext != null ) {
else if ( this instanceof EntityResultInitializer && entityInstanceFromExecutionContext != null ) {
this.entityInstance = entityInstanceFromExecutionContext;
registerLoadingEntity( rowProcessingState, entityInstance );
}
Expand Down Expand Up @@ -507,6 +510,26 @@ else if ( this.isEntityResultInitializer() && entityInstanceFromExecutionContext
}
}

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
Expand Down Expand Up @@ -990,6 +1013,11 @@ private void preLoad(RowProcessingState rowProcessingState) {
}
}

@Override
public boolean isInitialized() {
return isInitialized;
}

@Override
public EntityPersister getConcreteDescriptor() {
return concreteDescriptor;
Expand Down
Expand Up @@ -60,8 +60,7 @@ default EntityInitializer asEntityInitializer() {
return this;
}


default boolean isEntityResultInitializer() {
default boolean isInitialized() {
return false;
}
}
Expand Up @@ -83,6 +83,11 @@ public void resolveInstance(RowProcessingState rowProcessingState) {
return;
}

final EntityInitializer parentEntityInitializer = getParentEntityInitializer( parentAccess );
if ( parentEntityInitializer != null && parentEntityInitializer.isInitialized() ) {
return;
}

if ( !isAttributeAssignableToConcreteDescriptor( parentAccess, referencedModelPart ) ) {
return;
}
Expand Down Expand Up @@ -115,7 +120,7 @@ public void resolveInstance(RowProcessingState rowProcessingState) {
if ( referencedModelPart.isOptional()
&& parentAccess != null
&& !parentAccess.isEmbeddableInitializer()
&& isEnhancedForLazyLoading( parentAccess ) ) {
&& isEnhancedForLazyLoading( parentEntityInitializer ) ) {
entityInstance = LazyPropertyInitializer.UNFETCHED_PROPERTY;
}
else {
Expand All @@ -141,7 +146,7 @@ && isEnhancedForLazyLoading( parentAccess ) ) {
if ( entityInstance == null ) {
if ( parentAccess != null
&& !parentAccess.isEmbeddableInitializer()
&& isEnhancedForLazyLoading( parentAccess ) ) {
&& isEnhancedForLazyLoading( parentEntityInitializer ) ) {
return;
}
entityInstance = ( (UniqueKeyLoadable) concreteDescriptor ).loadByUniqueKey(
Expand Down Expand Up @@ -180,8 +185,16 @@ && isEnhancedForLazyLoading( parentAccess ) ) {
}
}

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();
}

Expand Down
Expand Up @@ -57,8 +57,4 @@ public String toString() {
return CONCRETE_NAME + "(" + getNavigablePath() + ")";
}

@Override
public boolean isEntityResultInitializer() {
return true;
}
}
Expand Up @@ -15,6 +15,7 @@
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;
Expand Down

0 comments on commit 2c81979

Please sign in to comment.