尝试返回内部 SELECT 语句中查询的对象的 JPA 查询出现 ClassCastException

问题描述 投票:0回答:1

我有以下 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
语句返回在内部查询中找到的对象(据我所知,它在内部被转换为 CTE(通用表)表达式)由 Hibernate 实现)。因此,我最好的猜测是,需要对
ChildObject
执行一些特殊操作,以便能够将其作为操作的一部分返回,因为它当前被识别为
SingleTableEntityPersister
,并且 Hibernate 期望
EntityAssociationMapping 
.

因此,我的问题是:

  • 为了获得
    ClassCastException
    ,我在原始查询中做错了什么?
  • 怎样才能让我的查询成功?
java hibernate jpa spring-data-jpa spring-data
1个回答
0
投票

我仍然需要找到令人满意的解释,但执行以下操作足以获得我正在寻找的结果:

@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
实体。

© www.soinside.com 2019 - 2024. All rights reserved.