用hibernate分页的时候遇到了个问题,就是获取总页数。
注意中间有一个个setProjection(null),用来把之前的分组取消。这算是一个hack吧,虽然在排序前进行总数计数能节约一部分性能,但依然是两次查询。例子中的选择条件是相当简单的,如果复杂一些呢,再来几个many-to-one或者one-to-many子查询呢?
现在流行的办法是用Criteria,在排序前先分组计数并返回值,然后在添加排序、分页。举例来说:
Session session = sessionFactory.getCurrentSession();
Criteria c = session.createCriteria(UserModel.class);
c.add(Restrictions.ge("id", 10));
c.add(Restrictions.le("id",20));
int t = ((Long) c.setProjection(Projections.rowCount())
.uniqueResult()).intValue();
c.setProjection(null);
c.setMaxResults(4);
c.addOrder(Order.desc("id"));
注意中间有一个个setProjection(null),用来把之前的分组取消。这算是一个hack吧,虽然在排序前进行总数计数能节约一部分性能,但依然是两次查询。例子中的选择条件是相当简单的,如果复杂一些呢,再来几个many-to-one或者one-to-many子查询呢?
针对我用的是mysql,百度到一种解决方案[1]:用select found_rows(),可以得到上一次查询的结果数。如果在查询中加上SQL_CALC_FOUND_ROWS,就可以忽略limit,也就是说得到我们要的总条目数,也就能得到总页数!
但奈何SQL_CALC_FOUND_ROWS并不是hql关键字,语法解析的时候就被pass了。于是乎花了一天的时间追踪hibernate源码(大部分时间都浪费在官网下的)
hibernate版本号:4.1.6 final
可能存在的问题:
(1)found_rows()的并行支持,考虑到hibernate中用了事务,加上mysql推出此函数的目的就是用于获取总页数的场景,心里稍宽慰。
参考: