转自: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. ubuntu安装jira步骤

    背景:前些日子在原来的一台云主机上已经部署了一个jira系统,使用一段时间后发现jira占用很多的系统资源,导致主机上的其他服务无法正常工作,于是老大新注册了一个云主机专门用于运行jira,可见公司对 ...

  2. 安装weblogic的步骤10.3.0.0

    一.安装前的注意事项: weblogic在安装前必须要有对应的jdk支持weblogic的运行.所以在安装之前一定要根据本机上安装的jdk来选择安装的weblgoic的什么版本.因为weblogic的 ...

  3. fltk demo

    背景: 基于microwindows nano-X上面运行fltk demo,是nano-X API 预留的fltk接口. 运行环境及程序版本: microwindows-0.89pre8 (源文件必 ...

  4. MYSQL 查看表定义的 4 种方法

    方法 1. show create table table_name;可以用这个看表的代码. show create table Strings; 方法 2. show full columns fr ...

  5. Windows下Node.js开发环境搭建

    1.http://nodejs.org/下载node.js运行环境安装 2.打开DOS命令行 .安装express框架 1 >npm install express 末尾显示如下为安装成功 .安 ...

  6. 几种MEMS陀螺仪(gyroscope)的设计和性能比较

    现在市场上的MEMS陀螺仪主要有SYSTRON.BOSCH和INVENSENSE设计和生产.前两者设计的陀螺仪属高端产品,主要用于汽车.后者的属低端产品,主要用于消费类电子,象任天堂的Wii.ADI2 ...

  7. linux之SQL语句简明教程---GROUP BY

    我们现在回到函数上.记得我们用 SUM 这个指令来算出所有的 Sales (营业额)吧!如果我们的需求变成是要算出每一间店 (Store_Name) 的营业额 (Sales),那怎么办呢?在这个情况下 ...

  8. 续上文----线性表之单链表(C实现)

    本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...

  9. 解决GitHub未配置SSH key提示错误信息

    git push -u origin master Permission denied (publickey). fatal: Could not read from remote repositor ...

  10. ID3算法 决策树 C++实现

    人工智能课的实验. 数据结构:多叉树 这个实验我写了好久,开始的时候从数据的读入和表示入手,写到递归建树的部分时遇到了瓶颈,更新样例集和属性集的办法过于繁琐: 于是参考网上的代码后重新写,建立决策树类 ...