StackOverflow when applying a load entity graphs to a query

Description

Assume the following entity and named entity graph:

@Entity @NamedEntityGraphs({ @NamedEntityGraph(name = "User.overview", attributeNodes = { @NamedAttributeNode("name") }) }) public class Sample { @Id @GeneratedValue private Integer id; @ManyToOne Sample parent; String name; }

and query execution trying to apply the entity graph as follows:

EntityGraph<?> entityGraph = em.getEntityGraph("User.overview"); em.createQuery("select s from Sample s", Sample.class) .setHint("javax.persistence.loadgraph", entityGraph) .getResultList();

This results in the following exception:

java.lang.StackOverflowError at java.base/java.lang.StringBuilder.<init>(StringBuilder.java:119) … couple of lines of logging removed at org.hibernate.sql.ast.spi.SqlAliasBaseImpl.generateNewAlias(SqlAliasBaseImpl.java:34) at org.hibernate.persister.entity.AbstractEntityPersister.resolvePrimaryTableReference(AbstractEntityPersister.java:1445) at org.hibernate.persister.entity.AbstractEntityPersister.createPrimaryTableReference(AbstractEntityPersister.java:1388) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.createTableGroupInternal(ToOneAttributeMapping.java:1838) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.lambda$createRootTableGroupJoin$5(ToOneAttributeMapping.java:1747) at org.hibernate.sql.ast.tree.from.LazyTableGroup.getTableGroup(LazyTableGroup.java:83) at org.hibernate.sql.ast.tree.from.LazyTableGroup.getTableReferenceInternal(LazyTableGroup.java:293) at org.hibernate.sql.ast.tree.from.LazyTableGroup.resolveTableReference(LazyTableGroup.java:246) at org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl.resolveSqlSelection(BasicEntityIdentifierMappingImpl.java:258) at org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl.generateFetch(BasicEntityIdentifierMappingImpl.java:388) at org.hibernate.sql.results.graph.entity.AbstractEntityResultGraphNode.afterInitialize(AbstractEntityResultGraphNode.java:62) at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.<init>(EntityFetchJoinedImpl.java:54) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.lambda$generateFetch$0(ToOneAttributeMapping.java:1257) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.withRegisteredAssociationKeys(ToOneAttributeMapping.java:1502) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.generateFetch(ToOneAttributeMapping.java:1232) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.generateFetch(ToOneAttributeMapping.java:106) at org.hibernate.sql.results.graph.FetchParent.generateFetchableFetch(FetchParent.java:105) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.buildFetch(BaseSqmToSqlAstConverter.java:7087) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.addFetch(BaseSqmToSqlAstConverter.java:7019) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.lambda$visitFetches$128(BaseSqmToSqlAstConverter.java:7069) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.hibernate.persister.entity.AbstractEntityPersister.visitFetchables(AbstractEntityPersister.java:6690) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitFetches(BaseSqmToSqlAstConverter.java:7069) at org.hibernate.sql.results.graph.AbstractFetchParent.afterInitialize(AbstractFetchParent.java:32) at org.hibernate.sql.results.graph.entity.AbstractEntityResultGraphNode.afterInitialize(AbstractEntityResultGraphNode.java:100) at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.<init>(EntityFetchJoinedImpl.java:54) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.lambda$generateFetch$0(ToOneAttributeMapping.java:1257) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.withRegisteredAssociationKeys(ToOneAttributeMapping.java:1502) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.generateFetch(ToOneAttributeMapping.java:1232) at org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping.generateFetch(ToOneAttributeMapping.java:106) at org.hibernate.sql.results.graph.FetchParent.generateFetchableFetch(FetchParent.java:105) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.buildFetch(BaseSqmToSqlAstConverter.java:7087) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.addFetch(BaseSqmToSqlAstConverter.java:7019) at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.lambda$visitFetches$128(BaseSqmToSqlAstConverter.java:7069)

The offender seems to be the parent reference, as it seems to kick off the type inspection over and over again. Please let me know if I can help diagnose this further.

Activity

Andrea BorieroJuly 22, 2022 at 12:54 PM

Hi,

after discussing with the other members of the team we decided to work on a solution to avoid the StackOverflow in case of self-reference associations eagerly loaded .

Andrea BorieroJuly 13, 2022 at 4:23 PM

yes I agree it is not clear, we have for sure to improve the doc and try to see if it possible to log a warning for such a mapping.

Oliver DrotbohmJuly 13, 2022 at 3:46 PM

Thanks! Switching to a lazy @ManyToOne does the trick. I am still not sure a misconfiguration of that kind should manifest as StackOverflowError, though. The linked to section of the docs creates the impression that you would use the lazy flag as optimization to avoid too many joins, but not that it wouldn’t work at all.

Andrea BorieroJuly 13, 2022 at 3:04 PM

I investigated the issue, and the StackOverflow is related to https://github.com/hibernate/hibernate-orm/blob/6.0/migration-guide.adoc#fetch-circularity-determination .

i was not able to reproduce it because by default in Hibernate tests assigns a value to hibernate.max_fetch_depth

in your cases there are 3 possible solutions:

  • set hibernate.max_fetch_depth

  • use a fetch graph

  • set the @ManyToOne to lazy

Andrea BorieroJuly 13, 2022 at 10:14 AM

Thanks a lot , I’m going to work on it!

Fixed

Details

Assignee

Reporter

Worked in

Fix versions

Affects versions

Priority

Created July 8, 2022 at 1:46 PM
Updated August 3, 2022 at 1:40 PM
Resolved August 2, 2022 at 6:36 PM

Flag notifications