From 8cc568ce1b554daa9a8f0a8d5d5b14324e87b9f4 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 13 Jun 2023 10:00:37 +0200 Subject: [PATCH] HHH-16743 StackOverflowError when loading a ManyToOne whith @Proxy(lazy=false) --- .../EntitySelectFetchInitializerBuilder.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) 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 47f8d58269..d02684be10 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 @@ -19,6 +19,10 @@ import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; +import static org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializerBuilder.BatchMode.BATCH_INITIALIZE; +import static org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializerBuilder.BatchMode.BATCH_LOAD; +import static org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializerBuilder.BatchMode.NONE; + public class EntitySelectFetchInitializerBuilder { public static AbstractFetchParentAccess createInitializer( @@ -94,10 +98,13 @@ public class EntitySelectFetchInitializerBuilder { FetchParentAccess parentAccess, AssemblerCreationState creationState) { if ( !entityPersister.isBatchLoadable() || creationState.isScrollResult() ) { - return BatchMode.NONE; + return NONE; } else if ( creationState.isDynamicInstantiation() ) { - return BatchMode.BATCH_INITIALIZE; + if ( canBatchInitializeBeUsed( entityPersister ) ) { + return BatchMode.BATCH_INITIALIZE; + } + return NONE; } while ( parentAccess.isEmbeddableInitializer() ) { final EmbeddableInitializer embeddableInitializer = parentAccess.asEmbeddableInitializer(); @@ -124,10 +131,22 @@ public class EntitySelectFetchInitializerBuilder { 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; + if ( canBatchInitializeBeUsed( entityPersister ) ) { + return BATCH_INITIALIZE; + } + return NONE; } } - return BatchMode.BATCH_LOAD; + return BATCH_LOAD; + } + + private static boolean canBatchInitializeBeUsed(EntityPersister entityPersister) { + if ( entityPersister.getRepresentationStrategy().getProxyFactory() == null + && entityPersister.hasSubclasses() ) { + // We cannot neither create a proxy nor instantiate the entity because we don't know the concrete type + return false; + } + return true; } enum BatchMode {