转自:http://blog.csdn.net/huqiub/article/details/4329541

分页在任何系统中都是非常头疼的事情,有的数据库在语法上支持分页,而有的数据库则需要使用可滚动游标来实现,并且在不支持可滚动游标的系统上只能使用单向游标逐步接近要取得的数据。
     Hibernate提供了一个支持跨系统的分页机制,这样无论底层是什么样的数据库都能用统一的接口进行分页操作。比如下面的代码就是从第500条开始取出100条记录:

Query q = session.createQuery("from FooBar as f");

q.setFirstResult(500);

q.setMaxResults(100);

List l = q.list();

那么Hibernate底层如何实现分页的呢?Hibernate根据Query拼装SQL语句的地方是在org.hibernate.loader.Loader类的prepareQueryStatement方法中,对分页支持的代码在这一段中可以发现:

if (useLimit)

{

sql = dialect.getLimitString(

sql.trim(), //use of trim() here is ugly?

useOffset ? getFirstRow(selection) : 0,

getMaxOrLimit(selection, dialect)

);

}

此处调用Dialect的getLimitString方法来得到不同平台的分页语句。
在MySQLDialect中是如下实现getLimitString方法的:

public String getLimitString(String sql, boolean hasOffset)

{

return new StringBuffer( sql.length()+20 )

.append(sql)

.append( hasOffset ? " limit ?, ?" : " limit ?")

.toString();

}

这是MySQL的专用分页语句,再来看Oracle9Dialect:

public String getLimitString(String sql, boolean hasOffset) {

sql = sql.trim();

boolean isForUpdate = false;

if ( sql.toLowerCase().endsWith(" for update") ) {

sql = sql.substring( 0, sql.length()-11 );

isForUpdate = true;

}

StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );

if (hasOffset) {

pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");

}

else {

pagingSelect.append("select * from ( ");

}

pagingSelect.append(sql);

if (hasOffset) {

pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");

}

else {

pagingSelect.append(" ) where rownum <= ?");

}

if ( isForUpdate ) {

pagingSelect.append( " for update" );

}

return pagingSelect.toString();

}

Oracle采用嵌套3层的查询语句结合rownum来实现分页,这在Oracle上是最好的方式,因为如果只是一层或者两层的查询语句的rownum不能支持order by。
此外Interbase,PostgreSQL,HSQL等也在语法级别上支持分页,具体实现可以查看相应的Dialect实现。如果数据库不支持分页的SQL语句,那么如果数据库支持可滚动游标,那么Hibernate就会采使用ResultSet的absolute方法直接移到查询起点;否则使用循环语句,通过rs.next一步步移动到要查询的数据处:

final int firstRow = getFirstRow( selection );

if ( firstRow != 0 )

{

if ( getFactory().getSettings().isScrollableResultSetsEnabled() )

{

// we can go straight to the first required row

rs.absolute( firstRow );

}

else

{

// we need to step through the rows one row at a time (slow)

for ( int m = 0; m < firstRow; m++ ) rs.next();

}

}

可见使用Hibernate,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试Scrollable,如果不支持Scrollable再采用rset.next()移动的办法。这样既兼顾了查询分页的性能,同时又保证了代码在不同的数据库之间的可移植性。

Hibernate实现分页的更多相关文章

  1. Hibernate中分页

    query.setFirstResult(4);query.setMaxResults(5);       这两个方法就是hibernate的分页

  2. hibernate 的分页查询

    hibernate的分页查询有个好处,就是不用管数据库方言.比如db2的分页查询很麻烦,但是用hibernate的方式,就完全不用管这些了 /* 使用HQL分页查询Customer信息 */ publ ...

  3. struts2+spring+hibernate 实现分页

    在这里要感谢下这位博友发表的博文 http://www.blogjava.net/rongxh7/archive/2008/11/29/243456.html 通过对他代码的阅读,从而自己实现了网页分 ...

  4. hibernate 实现分页查询语句、单条查询语句、多条查询语句、修改、删除语句

    package com.hanqi.test; import java.util.Date; import java.util.List; import org.hibernate.Query; im ...

  5. Hibernate简单分页

    5.1 准备工作 建立项目,加入jar 建立hibernate.cfg.xml 建立pojo类和对应的映射文件 5.2 建立vo类PageEntity package org.guangsoft.vo ...

  6. Hibernate 条件-分页查询

    这里我们继续跟着上一次的节奏继续学习Hibernate的查询. 1.条件查询一(占位符) 按照占位符的方式进行条件查询,这里query有一个setInteger(arg1, arg2)方法,其中第一个 ...

  7. hibernate mysql 分页时报错 显示的代码和sql server 类似 select top 1……

    [ERROR][com.alibaba.druid.filter.stat.StatFilter]merge sql error, dbType mysql, sql : select top 1 d ...

  8. 用Hibernate实现分页查询

    分页查询就是把数据库中某张表的记录数进行分页查询,在做分页查询时会有一个Page类,下面是一个Page类,我对其做了详细的注解: package com.entity; /** * @author:秦 ...

  9. Hibernate实现分页查询

    分页查询就是把数据库中某张表的记录数进行分页查询,在做分页查询时会有一个Page类,下面是一个Page类,我对其做了详细的注解: 1 package com.entity; 2 /** 3 * @au ...

随机推荐

  1. linux crontab设置

    cron来源于希腊单词chronos(意为“时间”),是linux系统下一个自动执行指定任务的程序.例如,你想在每晚睡觉期间创建某些文件或文件夹的备份,就可以用cron来自动执行. 服务的启动和停止 ...

  2. ButterKnife你需要知道的点

    ButterKnife,这个方便findViewById而使用的库,无数的应用在使用它,以注解来实现的他,对应用的性能影响几乎可以忽略,可以放心使用. 使用: compile 'com.jakewha ...

  3. [Linux Kernel]查看CentOS版本方法

    查看CentOS版本方法  有以下命令可以查看:   # lsb_release -a LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics- ...

  4. shonc项目中的设计资讯模块 php 字符串操作与正则表达式 strip_tags preg_match

    问题:当description 内容要求description的值选用资讯内容的前50个汉字.资讯内容可能有图片. 此时需要对输出的内容进行处理 php 正则表达式处理,编辑器输出的内容 只取图片: ...

  5. jQuery Validate 插件验证,,返回不同信息(json remote)自定义

    问题 申请账号需要确认该账号是存在 jquery.validate.js中的remote Jquery Ajax获取后台返回的Json数据后,添加自定义校验 解题思路:输入的登陆信息远程验证是否该账号 ...

  6. 今年暑假不AC(贪心)

    今年暑假不AC 点我 Problem Description “今年暑假不AC?”“是的.”“那你干什么呢?”“看世界杯呀,笨蛋!”“@#$%^&*%...” 确实如此,世界杯来了,球迷的节日 ...

  7. jquery hover延时

    var timer;    //绑定hover事件    $(function () {         $(".centercy img").hover(showPic, hid ...

  8. [转]linux下IPTABLES配置详解

    如果你的IPTABLES基础知识还不了解,建议先去看看.开始配置我们来配置一个filter表的防火墙.(1)查看本机关于IPTABLES的设置情况[root@tp ~]# iptables -L -n ...

  9. HDOJ-1002 A + B Problem II (非负大整数相加)

    http://acm.hdu.edu.cn/showproblem.php?pid=1002 输入的数都是正整数,比较好处理,注意进位. //非负大整数加法 # include <stdio.h ...

  10. IOS设备设计完整指南(转载)

    http://blog.sina.com.cn/s/blog_6cc9af670102vq12.html