使用Hibernate连接Sqlserver可以用分页功能吗?

03-09-10 hailwind
如题

好像是不支持的,hibernate把sybase和sqlserver归为一类,使用的是同一个SybaseDialect类,没有实现getLimitString()方法,不知为何?

robbin
2003-09-10 16:47
why not?

Hibernate List分页通常情况下采用JDBC2.0 scrollable Result来实现的。

feiyuwen
2003-09-10 16:52
可以在所有数据库上实现分页的:

Query q = sess.createQuery("from DomesticCat cat");

q.setFirstResult(20);

q.setMaxResults(10);

List cats = q.list();

Hibernate会自动根据dialect使用不同的方法:

对支持游标的使用游标

对Mysql使用limit ?,?

robbin
2003-09-10 17:13
Hibernate 根据Dialect来判断,看Hibernate源码 net.sf.hibernate.dialect.MySQLDialect:

public boolean supportsLimit() {
        return true;
}

public String getLimitString(String sql) {
	StringBuffer pagingSelect = new StringBuffer(100);
	pagingSelect.append(sql);
	pagingSelect.append(" limit ?, ?");
	return pagingSelect.toString();
}
<p>

net.sf.hibernate.dialect.Oracle9Dialect:

    public boolean supportsLimit() {
        return true;
    }

public String getLimitString(String sql) {
	StringBuffer pagingSelect = new StringBuffer(100);
	pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
	pagingSelect.append(sql);
	pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
	return pagingSelect.toString();
}
<p>

如果不支持的就采用scrollable resultset

robbin
2003-09-10 17:16
补充一句:

在Oracle上采用这种嵌套三层的sql语句来实现分页,我过去曾经在Oracle8i上做过测试,由于嵌套层次太多,效率其实很差。不过听说Oracle9i又优化过,可能性能有提高也说不定,我没用用过9i。找个时间来测一下Oracle分页的效率。

felix
2003-09-10 18:03
在代码中没有发现使用Scrollable rset实现的getLimitString

而且使用Scrollable rset 并不快(比rset.next n次),在大量数据时,

消耗资源也很大。

robbin
2003-09-10 18:04
测试出来了,还是3层嵌套速度快。

3万条记录的表,从第1万条开始查询100条记录取出:

Fetch Size = 50

Hibernate List: 60ms

JDBC Scrollable: 950ms

Fetch Size = 100

Hibernate List: 50ms

JDBC Scrollable: 940ms

3万条记录的表,从第2万条开始查询100条记录取出:

Fetch Size = 100

Hibernate List: 80ms

JDBC Scrollable: 1800ms

我算是搞明白了,Oracle的JDBC驱动的Scrollable原来就是用rset.next()一条一条循环过去的,真够烂的了。

oldma
2003-09-10 18:20
没错

对于oracle

用三层嵌套比用oracle jdbc的api来分页要快很多

虽然用三层嵌套越往后查越慢

by the way

oracle用游标分页怎么实现,效果好吗?

robbin
2003-09-10 18:28
用游标?那不是要写PL/SQL了吗?干吗搞那么麻烦呢?没有试过,只听说过能不用游标就不用游标的劝告,因为效率很低。

robbin
2003-09-10 18:42
> 如题

>

>好像是不支持的,hibernate把sybase和sqlserver归为一类,使用的是同一个SybaseDialect类,没有实现getLimitString()方法,不知为何?

如果SQL Server有支持分页的sql语句,你可以自己编写一个SQLServerDialect类,这样不就行了,可以在Hibernate里面使用SQL Server的分页语句了吗?

hailwind
2003-09-10 22:17
>>>>在Oracle上采用这种嵌套三层的sql语句来实现分页,我过去曾经在Oracle8i上做过测试,由于嵌套层次太多,效率其实很差。不过听说Oracle9i又优化过,可能性能有提高也说不定,我没用用过9i。找个时间来测一下Oracle分页的效率。

为什么我测试的效果很好呢?

我用的Oracle817,表中50万条记录

用三层嵌套,取49万条以后的20条,在PLSQL Dev里查询显示0.01秒!

hailwind
2003-09-10 22:26
>>>>>如果SQL Server有支持分页的sql语句,你可以自己编写一个SQLServerDialect类,这样不就行了,可以在Hibernate里面使用SQL Server的分页语句了吗?

Sqlserver是有的,也是利用嵌套查询,并且速度亦是非常地快,在查询分析器里测试,亦是50万的表,取49万以后的20条只要0.01秒

语句如下:

获取按照F1字段升序排序的,从m至n行记录

F1一定要做索引或主键,最好是主键

select t2.* from (Select top n-m t1.* from (Select top n * from Tablename as t order by t.F1) as t1 order by t1.F1 desc) as t2 order by t2.F1

select t2.* from

(

select top 20 t1.* from

(

select top 500020 * from dbgen as t order by t.F1

)

as t1 order by t1.F1 desc

)

as t2 order by t2.F1

hailwind
2003-09-10 22:27
>>>>>用三层嵌套,取49万条以后的20条,在PLSQL Dev里查询显示0.01秒!

前段时间测试的,有些记不太清楚了,Sqlserver和MySQL的好像是0.0x秒,Oracle的好像多些,不过无论如何不超过0.5秒。

猜你喜欢