javahibernatemigrationhibernate-6.x

After migrating to Hibernate6 "LazyTableGroup cannot be cast to class PluralTableGroup" exception


I am migrating a project from Spring Boot 2.7.18 to Spring Boot 3, and this causes a Hibernate upgrade as well from Hibernate 5.6 to Hibernate 6.1.7.

I had a rather complicated criteria query. After the migration the execution of that query results in the following exception:

class org.hibernate.sql.ast.tree.from.LazyTableGroup cannot be cast to class org.hibernate.sql.ast.tree.from.PluralTableGroup (org.hibernate.sql.ast.tree.from.LazyTableGroup and org.hibernate.sql.ast.tree.from.PluralTableGroup are in unnamed module of loader 'app')

Caused by: java.lang.ClassCastException: class org.hibernate.sql.ast.tree.from.LazyTableGroup cannot be cast to class org.hibernate.sql.ast.tree.from.PluralTableGroup (org.hibernate.sql.ast.tree.from.LazyTableGroup and org.hibernate.sql.ast.tree.from.PluralTableGroup are in unnamed module of loader 'app')
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.findActualTableGroup(BaseSqmToSqlAstConverter.java:2810)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeExplicitJoins(BaseSqmToSqlAstConverter.java:2763)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeAttributeJoin(BaseSqmToSqlAstConverter.java:2941)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeExplicitJoin(BaseSqmToSqlAstConverter.java:2775)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.lambda$consumeExplicitJoins$42(BaseSqmToSqlAstConverter.java:2759)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at org.hibernate.query.sqm.tree.domain.AbstractSqmFrom.visitSqmJoins(AbstractSqmFrom.java:260)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeExplicitJoins(BaseSqmToSqlAstConverter.java:2755)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeAttributeJoin(BaseSqmToSqlAstConverter.java:2941)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeExplicitJoin(BaseSqmToSqlAstConverter.java:2775)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.lambda$consumeExplicitJoins$42(BaseSqmToSqlAstConverter.java:2759)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at org.hibernate.query.sqm.tree.domain.AbstractSqmFrom.visitSqmJoins(AbstractSqmFrom.java:260)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeExplicitJoins(BaseSqmToSqlAstConverter.java:2755)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeJoins(BaseSqmToSqlAstConverter.java:2649)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.consumeFromClauseRoot(BaseSqmToSqlAstConverter.java:2624)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at org.hibernate.query.sqm.tree.from.SqmFromClause.visitRoots(SqmFromClause.java:80)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitFromClause(BaseSqmToSqlAstConverter.java:2365)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:1817)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:416)
    at org.hibernate.query.sqm.tree.select.SqmQuerySpec.accept(SqmQuerySpec.java:122)
    at org.hibernate.query.sqm.spi.BaseSemanticQueryWalker.visitQueryPart(BaseSemanticQueryWalker.java:213)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQueryPart(BaseSqmToSqlAstConverter.java:1679)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitSelectStatement(BaseSqmToSqlAstConverter.java:1477)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitSelectStatement(BaseSqmToSqlAstConverter.java:416)
    at org.hibernate.query.sqm.tree.select.SqmSelectStatement.accept(SqmSelectStatement.java:213)
    at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.translate(BaseSqmToSqlAstConverter.java:711)
    at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.buildCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:380)
    at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:300)
    at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:276)
    at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:571)
    at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:363)
    at org.hibernate.query.sqm.internal.QuerySqmImpl.list(QuerySqmImpl.java:1073)
    at org.hibernate.query.Query.getResultList(Query.java:94)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:405)
    at jdk.proxy2/jdk.proxy2.$Proxy315.getResultList(Unknown Source)
...

For the migration I used openrewrite and manual corrections. I read the Hibernate 6 upgrade guide also ( https://github.com/hibernate/hibernate-orm/blob/6.0/migration-guide.adoc ).

Also I inserted a trivial criteria query ( select everything from a table ) into the code just before the exception-throwing part and found that that works without problem.

Googling for "PluralTableGroup" or "LazyTableGroup" didn't help me either.

I would be really appreciate any help or hint regarding this!


Solution

  • Hibernate 6 made substantial internal API and type system changes, especially to its criteria query handling and the table group representation for SQL AST conversions. Code that worked in Hibernate 5, especially custom or advanced Criteria API queries involving collections (joins with @OneToMany or @ManyToMany relationships) may break due to these underlying changes.

    I suggest you start with a simple query and gradually start adding in your joins until you can isolate the exact point at which the error occurs.