HHH-16743 StackOverflowError when loading a ManyToOne whith @Proxy(lazy=false)

This commit is contained in:
Andrea Boriero 2023-06-13 10:00:37 +02:00 committed by Andrea Boriero
parent faf1536ccb
commit 8cc568ce1b
1 changed files with 23 additions and 4 deletions

View File

@ -19,6 +19,10 @@ import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; 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 class EntitySelectFetchInitializerBuilder {
public static AbstractFetchParentAccess createInitializer( public static AbstractFetchParentAccess createInitializer(
@ -94,10 +98,13 @@ public class EntitySelectFetchInitializerBuilder {
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
if ( !entityPersister.isBatchLoadable() || creationState.isScrollResult() ) { if ( !entityPersister.isBatchLoadable() || creationState.isScrollResult() ) {
return BatchMode.NONE; return NONE;
} }
else if ( creationState.isDynamicInstantiation() ) { else if ( creationState.isDynamicInstantiation() ) {
return BatchMode.BATCH_INITIALIZE; if ( canBatchInitializeBeUsed( entityPersister ) ) {
return BatchMode.BATCH_INITIALIZE;
}
return NONE;
} }
while ( parentAccess.isEmbeddableInitializer() ) { while ( parentAccess.isEmbeddableInitializer() ) {
final EmbeddableInitializer embeddableInitializer = parentAccess.asEmbeddableInitializer(); final EmbeddableInitializer embeddableInitializer = parentAccess.asEmbeddableInitializer();
@ -124,10 +131,22 @@ public class EntitySelectFetchInitializerBuilder {
if ( cacheAccess != null ) { if ( cacheAccess != null ) {
// Do batch initialization instead of batch loading if the parent entity is cacheable // 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 // 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 { enum BatchMode {