Hibernate 可以实现分页查询 如下
Query q = session.createQuery("from Cat as c");
q.setFirstResult(10000);
q.setMaxResults(20);
List l = q.list();
生成的sql 语句为
select top 10000 .... from Cat as c
分析:Hibernate 获取到 10000条记录过后再筛选出符合条件的20条记录。

再来看看Hibernate 的 dialect 对 sql server 怎样分页的
public String getLimitString(String querySelect, int offset, int limit) {
      if ( offset > 0 ) {
           throw new UnsupportedOperationException( "sql server has no offset" );
        }
       return new StringBuffer( querySelect.length() + 8 )
                .append( querySelect )
                .insert( getAfterSelectInsertPoint( querySelect ), " top " + limit )
                .toString();
  }
由此可以看出Hibernate对 sql server 分页全是采取 top 方式来处理。如记录有10W条以上的话到后面几页效率会非常低。从getLimitString(String querySelect, int offset, int limit)方法可以看出 sql server 不支持 offset 参数(均为0)!!

然而在sql server2005过后支持ROW_NUMBER() 函数,可用该函数大大提高分页效率。但现有的Hibernate api不支持该函数。我们可以重写public String getLimitString(String querySelect, int offset, int limit)方法来实现 ROW_NUMBER 分页,重写的方法如下:
    public String getLimitString(String querySelect, int offset, int limit ){
        int lastIndexOfOrderBy = getLastIndexOfOrderBy(querySelect);
        // 没有 order by 或第一页的情况下
        if(lastIndexOfOrderBy<0 || querySelect.endsWith(")") || offset==0)
            return super.getLimitString(querySelect, 0, limit);
        else {
            //取出 order by 语句
            String orderby = querySelect.substring(lastIndexOfOrderBy, querySelect.length());
            //取出 from 前的内容
            int indexOfFrom = querySelect.toLowerCase().indexOf("from");
            String selectFld = querySelect.substring(0,indexOfFrom);
            //取出 from 语句后的内容
            String selectFromTableAndWhere = querySelect.substring(indexOfFrom, lastIndexOfOrderBy);
            StringBuffer sql = new StringBuffer(querySelect.length()+100);
            sql.append("select * from (")
                .append(selectFld)
                .append(",ROW_NUMBER() OVER(").append(orderby).append(") as _page_row_num_hb ")
                .append(selectFromTableAndWhere).append(" ) temp ")
                .append(" where  _page_row_num_hb BETWEEN  ")
                .append(offset+1).append(" and ").append(limit);
            return sql.toString();
        }
    }
让offset参数有效还应重写 public boolean supportsLimitOffset() 方法
    public boolean supportsLimitOffset(){
        return true;
    }

完整的代码如下:
package org.jac.common;
import org.hibernate.dialect.SQLServerDialect;
public class JacSQLServerDialect extends SQLServerDialect {
    static int getLastIndexOfOrderBy(String sql){
        return sql.toLowerCase().lastIndexOf("order by ");
    }
   
    public String getLimitString(String querySelect, int offset, int limit ){
        int lastIndexOfOrderBy = getLastIndexOfOrderBy(querySelect);
        // 没有 order by 或第一页的情况下
        if(lastIndexOfOrderBy<0 || querySelect.endsWith(")") || offset==0)
            return super.getLimitString(querySelect, 0, limit);
        else {
            //取出 order by 语句
            String orderby = querySelect.substring(lastIndexOfOrderBy, querySelect.length());
            //取出 from 前的内容
            int indexOfFrom = querySelect.toLowerCase().indexOf("from");
            String selectFld = querySelect.substring(0,indexOfFrom);
            //取出 from 语句后的内容
            String selectFromTableAndWhere = querySelect.substring(indexOfFrom, lastIndexOfOrderBy);
            StringBuffer sql = new StringBuffer(querySelect.length()+100);
            sql.append("select * from (")
                .append(selectFld)
                .append(",ROW_NUMBER() OVER(").append(orderby).append(") as _page_row_num_hb ")
                .append(selectFromTableAndWhere).append(" ) temp ")
                .append(" where  _page_row_num_hb BETWEEN  ")
                .append(offset+1).append(" and ").append(limit);
            return sql.toString();
        }
    }
    //使offset 参数生效
    public boolean supportsLimitOffset(){
        return true;
    }
最后再 hibernate.cfg.xml 配置 dialect
<property name="dialect">
      org.jac.common.JacSQLServerDialect
</property>

测试结果如下:
Query q = session.createQuery("from Cat as c order by c.id asc"); //注意要加 order by 才能用到 ROW_NUMBER分页
q.setFirstResult(10000);
q.setMaxResults(20);
List l = q.list();
生成的sql 语句为
select * from (select   ....,ROW_NUMBER() OVER(order by cat0_.id asc) as _page_row_num_hb from
cat as cat0_) temp where _page_row_num_hb BETWEEN  10001 and 10020

hibernate 对 sql server 2005 分页改进的更多相关文章

  1. 解决hibernate对Sql Server分页慢的问题

    一.hibernate分页 hibernate对MsSql的伪分页 分页是web项目中比不可少的一个功能,数据量大的时候不能全部展示必然要用到分页技术.相信大家对hibernate中的分页都不陌生: ...

  2. 使用SQL Server 2005 新的语法ROW_NUMBER()进行分页的两种不同方式的性能比较

    相比在SQL Server 2000 中使用的分页方式,在SQL Server 2005中使用新的语法ROW_NUMBER()来分页效率要高出很多,但是很多人在使用ROW_NUMBER()这种分页方式 ...

  3. SQL Server 2005的几个新功能

    SQL Server 2005相对于SQL Server 2000改进很大,有些还是非常实用的. 举几个例子来简单说明 这些例子我引用了Northwind库. 1. TOP 表达式  SQL Serv ...

  4. 回首经典的SQL Server 2005

    原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com SQL Server是我使用时间最长的数据库,算起来已经有10年了.上世纪90年代,微软在软件开发的所有领域高歌猛 ...

  5. 转载--SQL Server 2005的XQuery介绍

    原文地址: http://bbs.51cto.com/thread-458009-1-1.html   引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...

  6. 配置MyEclipse+Hibernate连接Sql Server 2008出错

    下文主要是讲述最近配置MyEclipse连接Sql Server 2008时遇到的一个问题,而不关注如何配置Sql Server 2008支持TCP/IP连接.Hibernate如何操作Sql Ser ...

  7. SQL Server 存储过程分页

    每每面试,总会有公司问到分页.在下不才,在这里写几种分页,望路过的各位大神尽情拍砖. 先从创建数据库说起.源码如下 一.创建数据库 /********************************* ...

  8. Sql Server 2005的1433端口打开和进行远程连接

    参考地址:http://topic.csdn.net/u/20090828/16/e693935a-99b7-4090-a6bc-0123c91183eb.html 1.如何打开sql server  ...

  9. 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历

    原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇到需要向SQL Server插入批量数据,然后在存储过程中对这些数据进行进一步处理的情况.存储过 ...

随机推荐

  1. jquery中的属性和css

    jQuery中的属性用于获取或设置元素的属性 1.attr(),获取或设置所有相匹配的元素的属性值:removeAttr("attr"),移除所有相匹配的元素的属性 //html ...

  2. 判断IE版本的HTML语句详解<!--[if IE]> <![endif]--> - AnswerCard

    一个页面里面只能有一句这样的判断 我们常常会在网页的HTML里面看到形如[if lte IE 9]……[endif]的代码,表示的是限定某些浏览器版本才能执行的语句,那么这些判断语句的规则是什么呢?请 ...

  3. Android较低版本(<5.2) 页面默认Select选择框效果的BUG解决

    Bug描述: 使用低版本安卓(<5.2),在微信上打开网页,点击下拉框,会出现如下图所示的用来展示select选项的弹出框: 在选项较少的时候,可以向下滑动,将选项滑到底部 滑动前: 滑动后: ...

  4. 金典 SQL笔记(4)

    由于在本地笔记上写的.CSDN markdown编辑器仅仅支持.md格式导入, 图片没办法直接导进去.写的多了懒的一张一张图片切图上传; 直接整个文章切成图片上传上去了. watermark/2/te ...

  5. shell脚本加密

      如何保护自己编写的shell程序要保护自己编写的shell脚本程序,方法有很多,最简单的方法有两种:1.加密 2.设定过期时间,下面以shc工具为例说明: 一.下载安装shc工具shc是一个加密s ...

  6. jquery之checkbox

    //checkbox 数据回显 var publishRange=rowData.publishRange.split(","); for(var i = 0;i < pub ...

  7. 关于看似简单的eclipse中tomcat小猫图标消失的问题解决

    首先,这个问题出现在我新安装的虚拟机中,自己准备重新搭一套开发环境用于学习. 所以,出于好奇,自己从官网上把eclipse的最新版neo下下来尝尝鲜,刚安装好后发现与之前用的旧版基本相同,于是把相应的 ...

  8. Emoji表情在网页中显示

    最近遇到一个项目,客户手机上发送的表情要在电脑网页中显示,没有找到简便方法,于是有了以下方案. 由于Emoji表情传到后台是“口”,怎么找出接收数据中的表情是关键,各种搜索后,我用下面的正则表达式匹配 ...

  9. DataTable循环删除行

    1.如果只是想删除datatable中的一行,可以用DataRow的delete,但是必须要删除后让DataTable知道,所以就要用 到.AcceptChanges()方法,原因是这种删除只是标识性 ...

  10. UML类图常见的几种关系

    关系:泛化(Generalization),实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency) ...