我有以下 JPA 查询,它尝试查找父对象的所有符合特定条件的子对象,然后仅获取不同分区下的第一个:
@Repository
public interface MyRepository {
@Query("SELECT sorted_children.child_1 " +
" FROM ( " +
" SELECT child AS child_1, " +
" ROW_NUMBER() OVER (PARTITION BY child.field2, child.parent.field2 " +
" ORDER BY child.parent.field1 ASC) AS rowNum " +
" FROM ChildObject child " +
" WHERE child.field1 IN (?1) AND " +
" child.parent.field1 IN (?2) " +
" ) AS sorted_children" +
" WHERE sorted_children.rowNum = 1")
Set<ChildObject> findChildObjects(Set<Long> childField1, Set<Long> parentField1);
}
但由于某种原因我收到以下错误:
java.lang.ClassCastException: class org.hibernate.persister.entity.SingleTableEntityPersister cannot be cast to class org.hibernate.metamodel.mapping.EntityAssociationMapping (org.hibernate.persister.entity.SingleTableEntityPersister and org.hibernate.metamodel.mapping.EntityAssociationMapping are in unnamed module of loader 'app')
实体对象如下所示。
家长:
@Entity
@Table(name = "parent_table", schema = "schema")
public class ParentObject {
@Id
@Column(name = "id")
public Long id;
@Column(name = "field1")
public Long field1;
@Column(name = "field2")
public String field2;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
public Set<ChildObject> children;
}
孩子:
@Entity
@Table(name = "child_table", schema = "schema")
public class ChildObject {
@Id
@Column(name = "id")
public Long id;
@Column(name = "field1")
public Long field1;
@Column(name = "field2")
public String field2;
@ManyToOne
@JoinColumn(name = "parent_id", nullable = false, updatable = false)
public ParentObject parent;
}
我尝试了一些不同的有效查询,但它们没有返回我正在寻找的结果。
示例#1(不是第一个,也不是分区):
@Query("SELECT child " +
" FROM ChildObject child " +
" WHERE child.field1 IN (?1)")
Set<ChildObject> findChildObjects(Set<Long> field1);
示例#2(我正在获取父对象,而不是子对象):
@Query("SELECT sorted_children.parent " +
" FROM ( " +
" SELECT child.parent AS parent, " +
" ROW_NUMBER() OVER (PARTITION BY child.field2, child.parent.field2 " +
" ORDER BY child.parent.field1 ASC) AS rowNum " +
" FROM ChildObject child " +
" WHERE child.field1 IN (?1) AND " +
" child.parent.field1 IN (?2) " +
" ) AS sorted_children" +
" WHERE sorted_children.rowNum = 1")
Set<ParentObject> findParentObjects(Set<Long> childField1, Set<Long> parentField1);
我对示例 #2 的工作有点惊讶,因为它在
SELECT
语句返回一个对象的意义上非常相似。因此,我最好的猜测是,需要对 ChildObject
执行一些特殊操作,以便能够将其作为操作的一部分返回,因为它当前被识别为 SingleTableEntityPersister
,并且 Hibernate 期望 EntityAssociationMapping
.
因此,我的问题是:
ClassCastException
,我在原始查询中做错了什么?我仍然需要找到令人满意的解释,但执行以下操作足以获得我正在寻找的结果:
@Repository
public interface MyRepository {
@Query("SELECT child " +
" FROM ( " +
" SELECT child.id AS child_id, " +
" ROW_NUMBER() OVER (PARTITION BY child.field2, child.parent.field2 " +
" ORDER BY child.parent.field1 ASC) AS rowNum " +
" FROM ChildObject child " +
" WHERE child.field1 IN (?1) AND " +
" child.parent.field1 IN (?2) " +
" ) AS sorted_children" +
" INNER JOIN ChildObject child ON child.id = sorted_children.child_id" +
" WHERE sorted_children.rowNum = 1")
Set<ChildObject> findChildObjects(Set<Long> childField1, Set<Long> parentField1);
}
基本上,我不是在内部查询中返回
child
对象,而是返回 id
,这样我以后就可以获得整个 ChildObject
。
它不是最优雅的,也不是性能最好的查询,但它可以根据我的目的和限制完成工作。
我想我原来的查询返回的是
ChildObject
的某种投影,不适合重建原始 ChildObject
实体。也许是因为 rowNum
字段属于其中,是 SELECT
的一部分?无论如何,执行 INNER JOIN
来重新查询 ChildObject
有助于 Hibernate 了解要返回 ChildObject
实体。