Hibernate为什么忽略setMaxResults?

问题描述

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

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

结果是我收到以下警告 HHH000104:用集合访存指定的firstResult / maxResults;在内存中应用!。换句话说,Hibernate在内存上进行分页,因为它不在数据库上执行。对于此警告,我阅读了以下文章https://vladmihalcea.com/fix-hibernate-hhh000104-entity-fetch-pagination-warning-message/,但在将我的查询分为两个查询获取ID,然后获取这些ID的数据)之前,我想到了给setMaxResults。我仍然想知道为什么生成查询不符合ROWNUM的要求。

远程信息:

  • 数据库:Oracle 18
  • 对话框:org.hibernate.dialect.Oracle12cDialect
  • 休眠:5.3.15
  • JDK:11

解决方法

加入数据时,父项将被重复n次。例如:

select p from Post p join p.comments

如果一个帖子下有20条评论,则此帖子将被20次发送20次不同评论。 在这种情况下限制行没有意义,因为返回的帖子的实际数量将不等于页面大小。换句话说,将页面限制为20条记录只会返回一篇帖子。

,

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

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

Blaze-Persistence是JPA之上的查询构建器,它支持JPA模型之上的许多高级DBMS功能。随附的分页支持可解决您可能遇到的所有问题。

它还具有Spring Data集成,因此您可以像现在一样使用相同的代码,只需添加依赖项并进行设置: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 ...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...