使用 fetch 时,JPA + Hibernate 计数查询分页失败

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

我有 3 个实体,我们称它们为

Parent
Child1
Child2
Parent
与另外两个有
@OneToOne
关系:

@OneToOne(mappedBy = "team", fetch = FetchType.LAZY, optional = false)

使用

JpaSpecificationExecutor
并传递
Specification
Pageable
对象来执行查询。这两个关系都指定由
Specification
获取,因此生成的 SQL 看起来像这样:

select <a lot of fields from p, c1, c2>
from parent p
join child1 c1 <on something>
join child2 c2 <on something>
order by <some timestamp field>
limit M offset N

当结果数量超过单个页面所能容纳的数量时就会出现问题,因此 JPA 必须执行计数查询。

SimpleJpaRepository
实现这一点的方法是简单地应用您为新计数查询提供的相同规范。

这会导致异常:

org.hibernate.query.SemanticException: Query specified join fetching, but the owner of the fetched association was not present in the select list [SqmSingularJoin(Parent(332551168492391).child1(332551168541736) : child1)]]

我认为这是有道理的,因为生成的查询看起来像这样:

select count(*)
from parent p
join child1 c1 <on something>
join child2 c2 <on something>
order by <some timestamp field>

也就是说,我们连接表,但实际上并没有从中选择任何内容。

那么从这里开始的最佳方法是什么?

java hibernate jpa criteria criteria-api
1个回答
0
投票

当我稍微更改标题后,就会出现更多类似的问题,我偶然发现了这个答案。由于我无法从 JPQL 访问

countQuery
,这似乎是最好的解决方案。不过,我将其修改为不那么脆弱:

        if (Parent.class.isAssignableFrom(query.getResultType())) {
            root.fetch("child1");
            root.fetch("child1");
        } else {
            root.join("child2");
            root.join("child2");
        }

这似乎工作得很好,甚至在计数查询中省略了连接。只是不要忘记在支票中包含任何可能的预测(如果您使用的话)。

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