Fosztó Mátyás (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=712020%...
) *created* an issue
Hibernate ORM (
https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiYWZiYTgwZWY5...
) / Bug (
https://hibernate.atlassian.net/browse/HHH-16837?atlOrigin=eyJpIjoiYWZiYT...
) HHH-16837 (
https://hibernate.atlassian.net/browse/HHH-16837?atlOrigin=eyJpIjoiYWZiYT...
) UnknownTableReferenceException with @ManyToMany and @OrderBy and InheritenceType.JOINED
(
https://hibernate.atlassian.net/browse/HHH-16837?atlOrigin=eyJpIjoiYWZiYT...
)
Issue Type: Bug Affects Versions: 6.2.5 Assignee: Unassigned Components: hibernate-core
Created: 23/Jun/2023 01:07 AM Environment: Spring Boot 3.1.1, spring-data-jpa-3.1.1
Priority: Major Reporter: 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`:
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]
Here are the entity classes:
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@CreatedDate
protected Instant createdAt = Instant.now();
// getters, setters
}
@MappedSuperclass
public abstract class AnimalBase extends BaseEntity {
protected String name;
protected String species;
// getters, setters
}
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "animals" )
public class Animal extends AnimalBase {
private transient String unrelatedThing;
}
@Entity
@Table(name = "dogs" )
public class Dog extends Animal {
private int barkIntensity;
// getters, setters
}
@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<>();
}
@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;
}
And finally, the query which gets called
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);
}
Removing either the @OrderBy or the inheritance makes the exception disappear.
Here is a reproduction repo
(
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 )