hibernate 对 sql server 2005 分页改进
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 分页改进的更多相关文章
- 解决hibernate对Sql Server分页慢的问题
一.hibernate分页 hibernate对MsSql的伪分页 分页是web项目中比不可少的一个功能,数据量大的时候不能全部展示必然要用到分页技术.相信大家对hibernate中的分页都不陌生: ...
- 使用SQL Server 2005 新的语法ROW_NUMBER()进行分页的两种不同方式的性能比较
相比在SQL Server 2000 中使用的分页方式,在SQL Server 2005中使用新的语法ROW_NUMBER()来分页效率要高出很多,但是很多人在使用ROW_NUMBER()这种分页方式 ...
- SQL Server 2005的几个新功能
SQL Server 2005相对于SQL Server 2000改进很大,有些还是非常实用的. 举几个例子来简单说明 这些例子我引用了Northwind库. 1. TOP 表达式 SQL Serv ...
- 回首经典的SQL Server 2005
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com SQL Server是我使用时间最长的数据库,算起来已经有10年了.上世纪90年代,微软在软件开发的所有领域高歌猛 ...
- 转载--SQL Server 2005的XQuery介绍
原文地址: http://bbs.51cto.com/thread-458009-1-1.html 引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...
- 配置MyEclipse+Hibernate连接Sql Server 2008出错
下文主要是讲述最近配置MyEclipse连接Sql Server 2008时遇到的一个问题,而不关注如何配置Sql Server 2008支持TCP/IP连接.Hibernate如何操作Sql Ser ...
- SQL Server 存储过程分页
每每面试,总会有公司问到分页.在下不才,在这里写几种分页,望路过的各位大神尽情拍砖. 先从创建数据库说起.源码如下 一.创建数据库 /********************************* ...
- Sql Server 2005的1433端口打开和进行远程连接
参考地址:http://topic.csdn.net/u/20090828/16/e693935a-99b7-4090-a6bc-0123c91183eb.html 1.如何打开sql server ...
- 使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历
原文:使用XML向SQL Server 2005批量写入数据——一次有关XML时间格式的折腾经历 常常遇到需要向SQL Server插入批量数据,然后在存储过程中对这些数据进行进一步处理的情况.存储过 ...
随机推荐
- synchronized 与 Lock 的那点事
最近在做一个监控系统,该系统主要包括对数据实时分析和存储两个部分,由于并发量比较高,所以不可避免的使用到了一些并发的知识.为了实现这些要求,后台使用一个队列作为缓存,对于请求只管往缓存里写数据.同时启 ...
- (转)三星i9500/Galaxy S4 刷基带教程
一.手机基带是什么? 三星手机的基带用通俗的话来说就是手机中的一个负责信号调节并进行传输给系统的电路设置,基带的好坏直接影响到在同等信号强度下,手机的获取信号的能力. 二.为什么要刷基带? 常说的基带 ...
- Color 颜色码-英文名称-十六进制-RGB对照表
色 英文代码 形像颜色 HEX格式 RGB格式 LightPink 浅粉红 #FFB6C1 255,182,193 Pink 粉红 #FFC0CB 255,192,203 Crimson 猩红 # ...
- android 限制adb的访问目录
最近有个特殊的要求,engneer版本既要可以adb访问,且adb有的目录不能访问 如/data/目录. 用传统的chmod chgrp等无法满足客户需求,只能修改内核文件系统部分. 添加函数,检查路 ...
- Android学习之多点触摸并不神秘
最近研究了一下多点触摸,写了个利用多点触摸来控制图片大小和单点触摸控制图片移动的程序,和大家分享分享. Android中监听触摸事件是onTouchEvent方法,它的参数为MotionEvent,下 ...
- 【从零学习openCV】IOS7下的人脸检測
前言: 人脸检測与识别一直是计算机视觉领域一大热门研究方向,并且也从安全监控等工业级的应用扩展到了手机移动端的app,总之随着人脸识别技术获得突破,其应用前景和市场价值都是不可估量的,眼下在学习ope ...
- C语言--const修饰指针解析
这种例子在我们平时编程时可能会很少用,但是在面试时被问的可能性就很大了. 用const修饰指针,常见的情况可以分为四种: 1.const int *p; // p 可变,p 指向的对象不可 ...
- Qt install Phonon
sudo apt-get install libphonon-dev phonon-backend-gstreamer
- 利用ajax从txt读取数据
html代码: <div id="news"></div> txt: [ {"id":"1", "news ...
- CSS投影实现方式
备用素材: 1.png shadow.png 第一种方式: 利用负边距实现 最终效果图: <!DOCTYPE html> <html lang="en"&g ...