Hibernate进行时
有关Hibenrate及其相关工具的主页
随笔 - 0, 文章 - 16, 评论 - 29, 引用 - 0
数据加载中……
Hibernate3.2对sqlserver2005查询分页的处理
对Hibernate的查询分页,想必大家都比较熟悉了。setFirstResult()和setMaxResults()就可以搞定。但是使用sqlserver的朋友发现了吗,hibernate发送的分页语句中总是会有令人心烦的"select top 数字" 这样的字符串。比如你一页显示50条记录,现在要查询第100页的数据,则会出现"select top 50000"这样的语句,它是先把前5000条数据抓出到内存中,处理后仅返回最后的50条给你,但是其他的4500条不是多余的了吗?想想还真是憋火。
网上广为流传的一篇文章《实现Hibernate分页查询原理解读》(作者robbin)中已经讲的很清楚了,如果数据库自身支持分页查询,那么这种数据库的Dialect中的supportsLimit()方法将返回true,而Hibernate则才会去调用getLimitString()方法以得到分页的语句,比如对mysql来说是
pagingSelect.append(
"
limit ?, ?
"
);
而对于oracle是:
pagingSelect.append(
"
select * from ( select row_.*, rownum rownum_ from (
"
);
当然,sqlserver也不甘落后,好像非得supportsLimit它才舒服。它的supportsLimit()也是true,同时它的getLimitString()方法为:
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();
}
看到那个“top”的来历了吧。
而实事上,select top进行分页查询的效率非常之低,远不如下面的语句:
rs.absolute(firstRow);
从《实现Hibernate分页查询原理解读》中可以知道,rs.absolute(firstRow);执行的条件是数据库Dialect不支持分页查询,这句话有点绕,其实它的真正意思是“supportsLimit()方法返回的是false”。当supportsLimit()返回false时,Hibernate采用rs.absolute(firstRow);来进行分页查询。说到这里,大家心知肚明了吧。其实解决起来比较简单,你自己定义一个MySqlServer2005Dialect,继承于原来的org.hibernate.dialect.SQLServerDialect,覆盖其supportsLimit()方法,如下:
public
boolean
supportsLimit()
{
return
false
;
}
然后在hibernate配置文件中使用你自己的MySqlServer2005Dialect方言即可。
同时要注意的是,在Loader类的1471行有一个方法,它是:
/** */
/**
* Advance the cursor to the first required row of the <tt>ResultSet</tt>
*/
private
void
advance(
final
ResultSet rs,
final
RowSelection selection)
throws
SQLException
{
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分页查询原理解读》中描述的一样,如果你的jdbc支持scrollable,那就调用rs.absolute(firstRow)定位到第一行,否则的话,就一行一行去移动吧。因此在配置文件中有一项很重要:
<
prop key
=
"
hibernate.jdbc.use_scrollable_resultset
"
>
true
</
prop
>
(注意我用的是spring的配置文件)上述这一行其实可以不写,因为默认就是true了,但如果你显示地把它写上了,一定要设为true,如果为false的话,则记录集rs会一行一行去移动,还是很费事的。
posted on 2007-08-06 15:15
caixuetao
阅读(3675)
评论(4)
编辑
收藏
评论
#
re: Hibernate3.2对sqlserver2005查询分页的处理
回复
更多评论
这几天正在看蔡老师的Hibernate那本书啊!觉得写得很好!
这篇文章我转载到我blog上拉,不会介意吧!
2007-08-08 20:48 |
咖啡迷
#
re: Hibernate3.2对sqlserver2005查询分页的处理
回复
更多评论
我试了下好像不行, 全部都取了
2008-06-26 11:30 |
agua
#
re: Hibernate3.2对sqlserver2005查询分页的处理[未登录]
回复
更多评论
用最少1k~10w的数据量测试,结果说明,通过调用rs.absolute(firstRow)实现分页,对于性能的提高并没有帮助。
2010-03-08 17:55 |
C
#
re: Hibernate3.2对sqlserver2005查询分页的处理
回复
更多评论
我的也是不起作用!!!!!!! 任何方言配置了 都不起作用!
2011-05-09 09:49 |
刘玉海
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理
Powered by:
BlogJava
Copyright © caixuetao
导航
BlogJava
首页
新随笔
联系
聚合
管理
<
2011年5月
>
日
一
二
三
四
五
六
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
留言簿
(59)
给我留言
查看公开留言
查看私人留言
随笔分类
随笔
(rss)
文章档案
2007年8月 (1)
2007年4月 (1)
2006年7月 (3)
2006年6月 (1)
2006年3月 (2)
2006年2月 (3)
2006年1月 (1)
2005年10月 (4)
搜索
最新评论
1. re: HibernateTemplate中HibernateCallback的事务
不错 看了三个礼拜,终于看懂了!~~深度解析
--和大象掰腕子
2. re: HibernateTemplate中HibernateCallback的事务[未登录]
怎样获得session?
--aa
3. re: HibernateTemplate中HibernateCallback的事务[未登录]
评论内容较长,点击标题查看
--过客
4. re: Hibernate3.2对sqlserver2005查询分页的处理
我的也是不起作用!!!!!!! 任何方言配置了 都不起作用!
--刘玉海
5. re: Hibernate3.2对sqlserver2005查询分页的处理[未登录]
用最少1k~10w的数据量测试,结果说明,通过调用rs.absolute(firstRow)实现分页,对于性能的提高并没有帮助。
--C