为什么 Hibernate 忽略 setMaxResults?

Why does Hibernate ignore setMaxResults?

我使用 CriteriaQuery 和 TypedQuery 为我的一个表使用服务器端分页并设置以下值: typedQuery.setFirstResult(0); typedQuery.setMaxResults(100);

不幸的是,在 Oracle DB 上执行的生成的 SQL 查询中,我从未看到 ROWNUM 条件。我还在我的 TypedQuery 中添加了一个 ORDER BY,但是查询仍然执行简单的 select 而没有限制数据库结果。

因此,我收到以下警告 HHH000104:firstResult/maxResults specified with collection fetch;在内存中应用! 。换句话说,Hibernate 在内存上执行分页,因为它不在 DB 上执行。对于此警告,我阅读了以下文章 https://vladmihalcea.com/fix-hibernate-hhh000104-entity-fetch-pagination-warning-message/,但在将我的查询拆分为两个查询(检索 id,然后为这些 id 检索数据)之前,我想到了 setMaxResults 。我仍然想知道为什么生成的查询不是预期的 ROWNUM。

更多信息:

加入数据时,parent会被复制n次。例如:

select p from Post p join p.comments

如果 post 在一条 post 下有 20 条评论,那么这条 post 将被 return 编辑 20 次,有 20 条不同的评论。 在这种情况下限制行数没有意义,因为 returned post 的实际数量不会等于页面大小。换句话说,将页面限制为 20 条记录将 return 只有一条 post.

您必须了解,如果您 select 实体,则 first/max 结果适用于实体级别。如果您获取连接集合属性或使用实体图作为集合属性,您可以更改 JDBC 为每个实体返回的行的基数,即主实体行的每一行都为每个集合元素复制。其结果是,Hibernate 不能再使用 ROWNUM 进行分页,这就是为什么您在查询中看不到它的原因。如果删除提取连接,您将看到使用 ROWNUM。

话虽如此,这是 Blaze-Persistence 的完美用例。

Blaze-Persistence 是基于 JPA 的查询构建器,它支持基于 JPA 模型的许多高级 DBMS 功能。它附带的分页支持可以处理您可能遇到的所有问题。

它还有一个 Spring 数据集成,所以你可以像现在一样使用相同的代码,你只需要添加依赖项并进行设置:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-setup

Blaze-Persistence 有许多不同的分页策略可以配置。默认策略是将 id 查询内联到主查询中。像这样:

select u 
from User u 
left join fetch u.notes 
where u.id IN (
  select u2.id
  from User u2
  order by ...
  limit ...
)
order by ...