Fosztó Mátyás (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=712020%...
) *updated* an issue
Hibernate ORM (
https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNDJmNWJlMzUz...
) / Bug (
https://hibernate.atlassian.net/browse/HHH-16837?atlOrigin=eyJpIjoiNDJmNW...
) HHH-16837 (
https://hibernate.atlassian.net/browse/HHH-16837?atlOrigin=eyJpIjoiNDJmNW...
) UnknownTableReferenceException with @ManyToMany and @OrderBy and InheritenceType.JOINED
(
https://hibernate.atlassian.net/browse/HHH-16837?atlOrigin=eyJpIjoiNDJmNW...
)
Change By: Fosztó Mátyás (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=712020%...
)
Hello there!
We have encountered an issue when upgrading to spring boot 3, and it seems to be caused by
Hibernate. Hopefully this is the right place to report it.
When fetching a ManyToMany relationship which has an `@OrderBy` annotation present, and is
a subclass, with JOINED inheritence type, hibernate throws a
`UnknownTableReferenceException`:
{noformat}org.hibernate.sql.ast.tree.from.UnknownTableReferenceException: Unable to
determine TableReference (`animals`) for
`com.example.demo.model.Human.pets.{element}.name`
at
org.hibernate.sql.ast.tree.from.ColumnReferenceQualifier.resolveTableReference(ColumnReferenceQualifier.java:46)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.metamodel.mapping.internal.AbstractDomainPath.addSortSpecification(AbstractDomainPath.java:255)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.metamodel.mapping.internal.AbstractDomainPath.apply(AbstractDomainPath.java:148)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.metamodel.mapping.internal.AbstractDomainPath.apply(AbstractDomainPath.java:126)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.metamodel.mapping.ordering.OrderByFragmentImpl.apply(OrderByFragmentImpl.java:35)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.lambda$visitQuerySpec$18(BaseSqmToSqlAstConverter.java:2066)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:2065)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:434)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.query.sqm.tree.select.SqmQuerySpec.accept(SqmQuerySpec.java:125)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.spi.BaseSemanticQueryWalker.visitQueryPart(BaseSemanticQueryWalker.java:221)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQueryPart(BaseSqmToSqlAstConverter.java:1907)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitSelectStatement(BaseSqmToSqlAstConverter.java:1592)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitSelectStatement(BaseSqmToSqlAstConverter.java:434)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.tree.select.SqmSelectStatement.accept(SqmSelectStatement.java:222)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.translate(BaseSqmToSqlAstConverter.java:775)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.buildCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:345)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:268)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:244)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:518)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:367)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.hibernate.query.spi.AbstractSelectionQuery.getSingleResult(AbstractSelectionQuery.java:473)
~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at
org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:223)
~[spring-data-jpa-3.1.1.jar:3.1.1]
at
org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:92)
~[spring-data-jpa-3.1.1.jar:3.1.1]
at
org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:148)
~[spring-data-jpa-3.1.1.jar:3.1.1]
at
org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:136)
~[spring-data-jpa-3.1.1.jar:3.1.1]
at
org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
~[spring-data-commons-3.1.1.jar:3.1.1]
at
org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
~[spring-data-commons-3.1.1.jar:3.1.1]
at
org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
~[spring-data-commons-3.1.1.jar:3.1.1]
at
org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
~[spring-data-commons-3.1.1.jar:3.1.1]
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:72)
~[spring-data-commons-3.1.1.jar:3.1.1]
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
~[spring-tx-6.0.10.jar:6.0.10]
at
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
~[spring-tx-6.0.10.jar:6.0.10]
at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
~[spring-tx-6.0.10.jar:6.0.10]
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
~[spring-tx-6.0.10.jar:6.0.10]
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
~[spring-data-jpa-3.1.1.jar:3.1.1]
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
~[spring-aop-6.0.10.jar:6.0.10]
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
~[spring-aop-6.0.10.jar:6.0.10]
at jdk.proxy2/jdk.proxy2.$Proxy114.find(Unknown Source) ~[na:na]
at com.example.demo.Controller.test(Controller.java:21) ~[main/:na]{noformat}
Here are the entity classes:
{code:java}@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@CreatedDate
protected Instant createdAt = Instant.now();
// getters, setters
}{code}
{code:java}@MappedSuperclass
public abstract class AnimalBase extends BaseEntity {
protected String name;
protected String species;
// getters, setters
}{code}
{code:java}@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "animals")
public class Animal extends AnimalBase {
private transient String unrelatedThing;
}
{code}
{code:java}
@Entity
@Table(name = "dogs")
public class Dog extends Animal {
private int barkIntensity;
// getters, setters
}{code}
{code:java}
@Entity
@Table(name = "humans")
public class Human extends BaseEntity {
private String humanName;
@ManyToMany()
@OrderBy("name")
@JoinTable(name = "human_pet",
inverseJoinColumns = @JoinColumn(name = "pet_id", referencedColumnName =
"id"),
joinColumns = @JoinColumn(name = "human_id", referencedColumnName =
"id"))
private Set<Dog> pets = new LinkedHashSet<>();
}
{code}
{code:java}
@Entity
@Table(name = "id_cards")
public class IdCard extends BaseEntity {
private Long serial;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(unique = true)
private Human human;
}{code}
And finally, the query which gets called
{code:java}public interface IdCardRepository extends JpaRepository<IdCard, Long> {
@Query("select ic from IdCard ic " +
"left join fetch ic.human as h " +
"left join fetch h.pets")
IdCard find(Long id);
}{code}
Removing either the {{@OrderBy}} or the inheritance makes the exception disappear.
Here is a reproduction repo :
[
https://github.com/FrenchFriesFiesta/HHH-16837-repro|https://github.com/F...]
(
https://hibernate.atlassian.net/browse/HHH-16837#add-comment?atlOrigin=ey...
) Add Comment (
https://hibernate.atlassian.net/browse/HHH-16837#add-comment?atlOrigin=ey...
)
Get Jira notifications on your phone! Download the Jira Cloud app for Android (
https://play.google.com/store/apps/details?id=com.atlassian.android.jira....
) or iOS (
https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=Em...
) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100227- sha1:d138f7b )