From f15d6ee5fb587cdb9cc93d9b04fb149cf1475bae Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 25 Jan 2023 15:01:41 +0100 Subject: [PATCH] HHH-16025 Using BatchEntitySelectFetchInitializer with caching leads to caching wrong values --- .../graph/entity/AbstractEntityInitializer.java | 2 +- ...hInitializeEntitySelectFetchInitializer.java | 1 - .../EntitySelectFetchInitializerBuilder.java | 17 ++++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java index bb8dc15ae1..da10d01e80 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java @@ -988,7 +988,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces @Override public EntityPersister getConcreteDescriptor() { - return concreteDescriptor; + return concreteDescriptor == null ? entityDescriptor : concreteDescriptor; } @Override 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 57eb2a4139..7baaf8c7cf 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 @@ -19,7 +19,6 @@ import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.entity.LoadingEntityEntry; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; /** diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java index cbae196fc4..c9a8dbb205 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java @@ -6,8 +6,10 @@ */ package org.hibernate.sql.results.graph.entity.internal; +import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.metamodel.internal.StandardEmbeddableInstantiator; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; +import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; @@ -77,7 +79,10 @@ public class EntitySelectFetchInitializerBuilder { throw new IllegalStateException( "Should be unreachable" ); } - private static BatchMode determineBatchMode(EntityPersister entityPersister, FetchParentAccess parentAccess, AssemblerCreationState creationState) { + private static BatchMode determineBatchMode( + EntityPersister entityPersister, + FetchParentAccess parentAccess, + AssemblerCreationState creationState) { if ( !entityPersister.isBatchLoadable() || creationState.isScrollResult() ) { return BatchMode.NONE; } @@ -99,6 +104,16 @@ public class EntitySelectFetchInitializerBuilder { break; } } + if ( parentAccess != null ) { + assert parentAccess.getInitializedPart() instanceof EntityValuedModelPart; + final EntityPersister parentPersister = parentAccess.asEntityInitializer().getEntityDescriptor(); + final EntityDataAccess cacheAccess = parentPersister.getCacheAccessStrategy(); + if ( cacheAccess != null ) { + // Do batch initialization instead of batch loading if the parent entity is cacheable + // to avoid putting entity state into the cache at a point when the association is not yet set + return BatchMode.BATCH_INITIALIZE; + } + } return BatchMode.BATCH_LOAD; }