`

hibernate 对 sql server 2005 分页改进

阅读更多

引用链接:http://www.uandroid.com/home/space.php?uid=4&do=blog&id=49

 

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

分享到:
评论

相关推荐

    struts+hibernate+sql server2005分页的小项目

    **Struts、Hibernate和SQL Server 2005 分页小项目详解** 在软件开发中,尤其是Web应用,数据分页是一项重要的功能,它能够帮助用户有效地浏览大量数据,提高用户体验。本项目以"Struts+Hibernate+SQL Server 2005...

    Hibernate+sqlserver2000分页

    综上所述,`Hibernate+sqlserver2000分页`是一个结合了ORM框架和数据库分页策略的技术主题。在实际应用中,开发者需要根据业务需求选择合适的分页方法,并注意性能优化,如避免全表扫描,使用索引来加速查询等。理解...

    Hibernate 分页示例 SQLServer 数据库

    一个基于Hibernate 和 SQLServer 数据库的分页示例,所有文件和数据库备份都在,只是速度不怎么快,如果加上自动生成下拉框,速度就更慢了,单表、10008条测试数据,如果哪位大侠改进了查询速度望告之:vni2007@163....

    SSH框架+SQLServer实现分页的小项目

    通过研究这个项目,开发者可以学习到SSH框架的整合、Spring的bean管理和事务处理、Hibernate的数据库操作,以及SQLServer的分页查询技巧。同时,对于提高Web应用的用户体验,理解分页原理和实现方式也是必不可少的。

    hibernate SQLServer2008Dialect

    SQLServer2008Dialect 优化了原来的分页查询数据方法以及在生成SQL时表后增加了with(nolock)

    hibernate分页Hibernate 分页的设计和编码

    标题与描述均提到了“Hibernate分页的设计和编码”,这表明文章主要聚焦于如何在Hibernate框架中实现数据分页功能。下面将详细解析这一主题的关键知识点。 ### Hibernate分页概念 Hibernate是Java环境下一个开放源...

    Struts2+Hibernate3.2+spring2.0+sqlserver2000

    Struts2、Hibernate3.2、Spring2.0和SQL Server 2000是Java Web开发中的四个关键组件,它们构成了一个强大的企业级应用框架,通常被称为SSH2(Struts2、Spring2、Hibernate2)集成框架。下面将详细阐述这些技术以及...

    com.microsoft.sqlserver.jdbc.SQLServerException: 只进结果集不支持请求的操作 解决方案

    本文将深入探讨标题和描述中提到的“com.microsoft.sqlserver.jdbc.SQLServerException: 只进结果集不支持请求的操作”这一异常,以及如何在使用Hibernate、Struts进行分页时避免这一问题。我们将从异常的根本原因...

    在JDBC,hibernate中实现分页

    String a = "jdbc:sqlserver://" + a1 + ";DatabaseName=KQ"; int rowTotal = 0; String sql = "SELECT COUNT(*) FROM basic WHERE deptid='" + data.getId() + "'"; try { Connection con = DriverManager....

    VCE远程教育(struts1.2-hibernate3.1-spring2.0+sqlserver2005)

    SSH框架通过Hibernate与SQLServer2005进行交互,执行SQL语句来实现数据的增删改查及分页查询,确保了数据操作的高效性和一致性。 **其他技术** - **分页**:在大型应用中,分页是必不可少的功能,它可以提高页面...

    Hibernate中的query 分页.doc

    在Java的持久化框架Hibernate中,分页查询是常见的需求,尤其在处理大量数据时,为了提高用户体验,分页展示数据至关重要。本文将探讨Hibernate中两种主要的分页方式:`query.scroll()`和使用`query.setFirstResult...

    远程教育系统(Struts1.2+Hibernate3.1+Spring2.0+Tomcat5.0+SqlServer2005)

    远程教育系统是一个基于Java技术栈的在线学习平台,利用了Struts1.2、Hibernate3.1、Spring2.0和Tomcat5.0等组件,搭配SqlServer2005数据库,构建了一个功能完善的系统。这里我们将深入探讨这些技术及其在远程教育...

    SQL分页加载数据demo

    8. **分页插件和框架**:在开发环境中,许多ORM框架如Hibernate、MyBatis提供了分页插件,可以简化分页操作,避免手动编写复杂的SQL。 9. **分页与排序**:分页通常与排序结合使用,确保每次加载的都是有序的数据。...

    hiberate SQL Server 2000 存储过程.pdf

    标题与描述中的关键词“hibernate SQL Server 2000 存储过程”指出了本文档的主题,即在Hibernate框架下如何与SQL Server 2000的存储过程进行交互。下面将深入探讨这一主题,包括为什么在Hibernate中使用存储过程、...

    hibernate中实现真分页和假分页技术

    而真分页,又叫物理分页,它是直接在数据库层面进行分页操作,只加载当前页的数据,对内存压力小,适用于大数据量的场景。 ### Hibernate中的假分页 在Hibernate中,实现假分页通常借助于Criteria API或者HQL...

    完整Struts2 HIBERNATE实现分页

    &lt;property name="hibernate.connection.url"&gt;jdbc:sqlserver://127.0.0.1:1433;DatabaseName=Tb_soft &lt;property name="hibernate.connection.username"&gt;sa &lt;property name="hibernate.connection.password"&gt;...

    用Struts+Hibernate做的分页

    在JSP中,你可以使用JSTL(JavaServer Pages Standard Tag Library)或者其他标签库来动态生成分页链接,根据当前页码计算出其他页码,并展示数据列表。同时,需要在页面上显示页码和每页记录数的输入框,以便用户...

    hibernate商品分页展示

    4. **SQL查询**:在SQL中,我们可以使用`LIMIT`和`OFFSET`(MySQL)或`FETCH NEXT`和`OFFSET`(SQL Server)来实现分页查询。 5. **数据处理**:查询结果返回后,应用需要对数据进行处理,如转换为对应的Java对象,...

    hibernate jsp 分页Demo

    1. **Hibernate**: Hibernate是一个开源的Java库,它提供了对象关系映射(ORM)解决方案,允许Java开发者将Java对象与关系数据库的表进行映射,减少了对SQL的直接依赖。在本项目中,Hibernate被用来执行数据库查询,...

    Hibernate+Servlet+jsp实现分页

    **Hibernate** 是一个强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库,而无需直接编写SQL语句。在分页实现中,Hibernate提供了Criteria API或HQL(Hibernate Query Language)来执行带有分页...

Global site tag (gtag.js) - Google Analytics