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

关于Hibernate分页类和jdbc的sql分页完美融合 NULL 博文链接:https://jeffenchung.iteye.com/blog/1472402 立即下载

相关推荐

SQLServer2008Dialect

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

基于SqlServer+hibernate的简单分页查询

目前项目中用分页查询数据的方式,通过webService把数据循环查询出来传给对方存储,用到了分页。在此我们只需要看分页逻辑代码(相当于ServiceImpl),和Dao层代码(分页查询的SQL)即可。 分页逻辑代码块如下(放在ServiceImpl里): try { /****************** 分页每次取100条记录 **********************/

黄三yeah的Java技术空间 1549

Ibatis SQLServerDialect 2008 分页

Ibatis SQLServerDialect 2008 分页 可实现SQLServerDialect 分页 支持ibatis3

【转载】hibernate 对sqlserver 分页的支持

Hibernate3.2对sqlserver2000查询分页的处理 对Hibernate的查询分页,想必大家都比较熟悉了。setFirstResult()和setMaxResults()就可以搞定。但是使用 sqlserver的朋友发现了吗,hibernate发送的分页语句中总是会有令人心烦的"select top 数字" 这样的字符串。比如你一页显示50条记录,现在要查询第...

moon_hunter的专栏 504

微信小程序使用ucharts折线图,有负数显示0刻度线

当数据有负数和正数的时候默认不会显示0刻度线,不方便看出正负对比。

欢迎来到我的博客!在这里,我将分享我在前端开发方面的知识和经验。让我们一起探索前端开发的无限可能! 1579

免Root抓包神器Packet Capture:安卓App数据捕获全攻略

本文详细介绍了免Root安卓抓包神器Packet Capture的安装与使用全攻略。通过利用安卓系统的VPN Service API,该工具无需Root权限即可捕获并解密App的HTTP/HTTPS网络流量。文章从核心原理、证书安装、实战抓包步骤到结果分析与常见问题排查,提供了完整指南,是移动端开发、安全测试和数据分析的实用利器。

weixin_29232507的博客 1073

Hibernate的优化:分页

[color=darkblue][b][size=medium]有同学强调我对sql server的分页不了解,在mssql 2000之前只能通过top进行分页。我没有说top分页不对,我是说在hibernate的sql server方言里面,针对sql server 的top分页是不对的。至少在我使用的版本里是不对的。而且有很多同学也遇到和我类似的问题。请大家打开hibernate的showsq...

我的角落 311

国产信创服务器软硬件兼容情况1 --- ARM架构

信创,即信息技术应用创新产业,它是数据安全、网络安全的基础,也是新基建的重要组成部分...

一只猿的自我修养 4741

收藏一个HIBERNATE对SQL SERVER 2005分页支持的问题

收藏一个HIBERNATE对SQL SERVER 2005分页支持的问题, 原来HB没为2005,2008提供了更优质的分页, 见 http://www.iteye.com/topic/721903

jackyrongvip的专栏 767

Windows10下部署Heygem进行数字人生成

对于使用Heygem生成数字人,需要注意几个问题: + 需要使用Nvidia的显卡。 + 需要在Windows上进行本地部署。主要原因为客户端是Windows的,客户端对上传的视频写入硬编码的`D:\heygem_data\voice\data`目录,需要在容器上读取这些文件。 + 需要在Windows上部署Docker,将Windows的目录映射到容器中,由容器中的服务进行读取。 + 需要特别注意,一定要有D盘,这个D盘是Windows的D盘,不能是插入的USB设备后产生的D盘。 + 需要下载3个Doc

冀辉的博客 5619

Windows报错“The system cannot find the file specified“的PATH环境变量解决方案

摘要: Windows系统中出现"The system cannot find the file specified"错误通常因PATH环境变量配置问题导致。本文提供解决方案:1)检查并修正PATH变量(通过命令行或图形界面添加缺失路径);2)确认程序安装路径及拼写无误;3)恢复误改的系统变量。示例演示了Python路径配置及无效路径清理方法,建议谨慎修改变量、使用绝对路径并定期检查。附参考表格详述操作步骤,帮助用户高效解决问题并优化系统环境。

shejizuopin的博客 3515

hibernate 3.2.7 支持SQL SERVER 2005+的分页

由于hibernate 3.2.7是用top处理mssql 查询分页,效率不高。由于在 3.6.x 版本中已经有改进的代码,因此从最近的版本hibernate-distribution-3.6.10.Final-dist.tar.gz中拷贝出SQLServer2005Dialect.java、SQLServer2008Dialect.java 具体目录是 hibernate-distrib

Yewberry 的点滴积累 2977

【知识分享】车载以太网PCB布局设计指南

本文将深入探讨在设计车载以太网设备的印刷电路板(PCB)时需要着重考虑的若干关键主题。这些主题广泛涵盖了数据布线设计,以确保其符合信号完整性(SI)和电磁兼容性(EMC)标准;外部元器件的合理摆放;以及采取有效的抗电磁干扰(EMI)布局策略等方面。通过全面且细致地处理这些关键环节,能够显著提升车载以太网设备的性能与可靠性。

一只豌豆象的博客 1352

win7下Hibernate连接SQLEXPRESS 2005

首先,下载jdbc驱动包: 微软官方网址: http://www.microsoft.com/zh-CN/download/details.aspx?displaylang=en&id=11774 解压出来后,把sqljdbc4.jar文件随便放到哪个盘,比如F盘下,因为原来解压出来的文件夹名称是带有空格的,在配置环境变量时是不允许有空格的 然后配置环境变量classpath 然

.net已寻山前道,旁路Java重头越 1254

uniapp - H5网页uni.getLocation报错getLocation:fail Geolocation permission denied.Get ipLocation failed.

uni.getLocation getLocation:fail Geolocation permission denied.Get ipLocation failed.,uni.getLocation定位失败,uni-app getLocation()无法获取定位,一直fail()uniapp移动端h5网页,uniApp微信内置浏览器定位失败,如何解决这个问题,uniapp h5 uni.getLocation获取位置失败怎么办,UNI-APP获取当前位置,uni.getLocation定位失败,unia

🏆 前端领域优质创作者 4241

【立创EDA-PCB设计基础】4.模块化布局

本文对本专栏绘制的原理图进行模块化布局,首先进行预布局(将每个模块放一起),然后进行精细化布局(按照原理图来精细化布局)。

嵌入式阿齐Archie 3万+

Hibernate3.2对sqlserver2005查询分页的处理

对Hibernate的查询分页,想必大家都比较熟悉了。setFirstResult()和setMaxResults()就可以搞定。但是使用sqlserver的朋友发现了吗,hibernate发送的分页语句中总是会有令人心烦的"select top 数字" 这样的字符串。比如你一页显示50条记录,现在要查询第100页的数据,则会出现"select top 50000"这样的语句,它是先把前5000条

远 823

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

项目中Hibernate的优化:分页

本文转自:http://www.iteye.com/topic/721903。   提到Hibernate,好多人都用“垃圾”,“效率太低”这样的字眼评价。其实任何一个框架的产生都是有原因的,这些为企业级开发产生的框架最初只是为 了简化开发,或许会有一些影响性能的地方。但是通过配置和巧妙的办法,完全可以规避这些问题,发挥最大的效果。至少目前我的项目,日均pv在500w左右 目前还没发现什么...

sue8534091的博客 377

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

mssql server2005 hibernate配置

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> com.microsoft.sqlserver.jd

岁月无情人有情 1470

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

上一篇: 怎样卸载IE7?
下一篇: IE和FF下输入框blur事件流程处理的差别引起的focus兼容性问题
rush2012
博客等级 码龄14年 2粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值