在研究Hibernate的分页方法query.setFirstResult和query.setMaxResults方法时:
setsession.createQuery(selecthql).setFirstResult(firstResult).setMaxResults(maxResult).list();
把sql打印出来,发现sql语句中是根据rownum来分页的,以前就知道,只是没有去用sql来实现。这次发现了
一个细节问题。特意发上来备案。
rownum:oracle在建表的时候会给每个表分配一个虚拟列,也可以说隐藏列,是看不见的。如其意,用数字来
标识每一行,第一行为1,第二行为2,如此类推.实现分页时,它很有效.
情况1: 在没有group by ,order by 的sql里,rownum能很好的在where里使用,例子:
select t.*,rownum tt from ds_keyword_day_count_num t where rownum <10,这里的rownum会默认
使用该表的primary key来分配数字.
select t.*,rownum tt from ds_keyword_day_count_num t where rownum<100 order by t.id desc
情况2: 有group by,order by的sql里,查询得到的结果是整理过的
2.1 要获得分组排序后的第一行:
select dd.* from (select t.*,rownum tt from ds_keyword_day_count_num t
order by t.id desc) dd where rownum =1
2.2 要获得分组排序后的前100行:
select rown_.*,rownum rownu_ from (select * from ds_keyword_day_count_num t
order by t.id desc) rown_ where rownum<100
2.3 要获得分组排序后的第50行到100行:
select tt.*,rownum rr from(select rown_.*,rownum rownu_ from
(select * from ds_keyword_day_count_num t order by t.id desc) rown_
where rownum<100) tt where rownu_>50
注意:这里是使用别名rownu_来做 >50 的条件,在嵌套的第2个select里把rownum作为一个字段先存储起来,
之后再最外层的select来对这个rownu_(别名)进行正常的 >操作.
使用rownum直接 > 操作是不行的.需要分两步操作.这里可从hibernate生成的sql里看出.
如果一步操作-----
如: select rown_.*,rownum rownu_ from (select * from ds_keyword_day_count_num t order by t.id desc) rown_
where rownum<100 and rownum>50
会返回空.原因是
参考文档:Oracle 9i SQL Reference的rownum描述的:
对于rownum的条件测试如果是大于一个正整数会返回false,当游标移动到第一行时,会给rownum赋为1,这时返回false,
当游标从第2行开始时select时,rownum又重新赋予1,这样如此反复,始终返回false.
所以对rownum的大于操作是无效的,需要如2.3的把rownum值赋予一个别名来判断