HHH-16025 Using BatchEntitySelectFetchInitializer with caching leads to caching wrong values

This commit is contained in:
Andrea Boriero 2023-01-25 15:01:41 +01:00 committed by Andrea Boriero
parent ac0a27eca2
commit f15d6ee5fb
3 changed files with 17 additions and 3 deletions

View File

@ -988,7 +988,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
@Override @Override
public EntityPersister getConcreteDescriptor() { public EntityPersister getConcreteDescriptor() {
return concreteDescriptor; return concreteDescriptor == null ? entityDescriptor : concreteDescriptor;
} }
@Override @Override

View File

@ -19,7 +19,6 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.entity.LoadingEntityEntry; import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
/** /**

View File

@ -6,8 +6,10 @@
*/ */
package org.hibernate.sql.results.graph.entity.internal; 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.internal.StandardEmbeddableInstantiator;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
@ -77,7 +79,10 @@ public class EntitySelectFetchInitializerBuilder {
throw new IllegalStateException( "Should be unreachable" ); 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() ) { if ( !entityPersister.isBatchLoadable() || creationState.isScrollResult() ) {
return BatchMode.NONE; return BatchMode.NONE;
} }
@ -99,6 +104,16 @@ public class EntitySelectFetchInitializerBuilder {
break; 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; return BatchMode.BATCH_LOAD;
} }