简体   繁体   English

Hibernate:使用 setFirstResult 和 setMaxResult 进行分页

[英]Hibernate: Pagination with setFirstResult and setMaxResult

I'm working on a Java EE project that uses Hibernate as ORM framework.我正在开发一个使用 Hibernate 作为 ORM 框架的 Java EE 项目。 In order to paginate the results of queries, I'm using the .setFirstResult and .setMaxResult methods (Criteria API).为了对查询结果进行分页,我使用了 .setFirstResult 和 .setMaxResult 方法(Criteria API)。

The problem is that the first page is displayed correctly but when I go to page 2, I have the first result displayed equal as the last result of page one.问题是第一页显示正确,但是当我转到第 2 页时,我显示的第一个结果与第一页的最后一个结果相同。

By switching the logging level to debug I've managed to catch the SQL query that Hibernate builds.通过将日志记录级别切换到调试,我设法捕获了 Hibernate 构建的 SQL 查询。 They are:他们是:

-- First page query (results from 1 to 10)
select * from ( select this_.DT_FINE_VAL as DT1_5_0_, this_.DT_INI_VAL as DT2_5_0_, this_.CD_TIPO_PERIODO as CD3_5_0_, this_.DT_AGGIORNAMENTO as DT4_5_0_, this_.DT_INSERIMENTO as DT5_5_0_, this_.CD_USERID_AGG as CD6_5_0_, this_.CD_USERID_INS as CD7_5_0_ from GPER0_POVS2.T_POVS2_PERIODI_FUNZ this_ order by this_.CD_TIPO_PERIODO desc ) where rownum <= 10;

-- Second page query (results from 11 to 20)
select * from ( select row_.*, rownum rownum_ from ( select this_.DT_FINE_VAL as DT1_5_0_, this_.DT_INI_VAL as DT2_5_0_, this_.CD_TIPO_PERIODO as CD3_5_0_, this_.DT_AGGIORNAMENTO as DT4_5_0_, this_.DT_INSERIMENTO as DT5_5_0_, this_.CD_USERID_AGG as CD6_5_0_, this_.CD_USERID_INS as CD7_5_0_ from GPER0_POVS2.T_POVS2_PERIODI_FUNZ this_ order by this_.CD_TIPO_PERIODO desc ) row_ where rownum <= 20) where rownum_ > 10;

It seems that the second query is "wrong".似乎第二个查询是“错误的”。 I'm using Oracle as DBMS.我使用 Oracle 作为 DBMS。 Could this be an Hibernate bug?这可能是 Hibernate 的错误吗? Can someone help me?有人能帮我吗?

Thanks.谢谢。

EDIT: This is the code:编辑:这是代码:

Session currentSession = getCurrentSession();
Criteria criteria = currentSession.createCriteria(PeriodoFunz.class);
criteria.setResultTransformer(Criteria.ROOT_ENTITY);
Order order = paginationInfo.isAsc() ? Order.asc(paginationInfo.getOrderBy()) : Order.desc(paginationInfo.getOrderBy());
criteria.addOrder(order);
....
criteria = criteria.setFirstResult(paginationInfo.getFromRecord()).setMaxResults(paginationInfo.getPageSize());
List<PeriodoFunz> result = criteria.list();

It seems that your order criteria leads to a SQL query that is not stable (returns the same result rows in different order for the queries). 您的订单标准似乎导致SQL查询不稳定 (为查询返回不同顺序的相同结果行)。

You can circumvent this by adding a second order criteria for a unique attribute, eg the ID: 您可以通过为唯一属性添加第二个订单条件来避免这种情况,例如ID:

Order order = paginationInfo.isAsc() ? Order.asc(paginationInfo.getOrderBy()) : Order.desc(paginationInfo.getOrderBy());
criteria.addOrder(order);
Order orderById = paginationInfo.isAsc() ? Order.asc("id") : Order.desc("id");
criteria.addOrder(orderById);

read this https://blogs.oracle.com/oraclemagazine/on-rownum-and-limiting-results 阅读此https://blogs.oracle.com/oraclemagazine/on-rownum-and-limiting-results

One important thing about using this pagination query is that the ORDER BY statement should order by something unique . 使用此分页查询的一个重要事项是ORDER BY语句应按唯一的顺序排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM