Hibernate分页的“真”与“假”,取决于所指定的方言(Dialect)。分析了一下Hibernate中相关的源代码,目前的结论是:
OracleDialect、Oracle9Dialect、MySQLDialect、MySQL5Dialect是真分页,SQLServerDialect是假分页。
Hibernate 可以实现分页查询 如下
1 |
Query q = session.createQuery( "from Cat as c" );
|
2 |
q.setFirstResult( 10000 );
|
生成的sql 语句为
select top 10000 .... from Cat as c
分析:Hibernate 获取到 10000条记录过后再筛选出符合条件的20条记录。
再来看看Hibernate 的 dialect 对 sql server 怎样分页的
1 |
public String getLimitString(String querySelect, int offset, int limit) {
|
3 |
throw new UnsupportedOperationException( "sql server has no offset" );
|
5 |
return new StringBuffer( querySelect.length() + 8 )
|
7 |
.insert( getAfterSelectInsertPoint( querySelect ), " top " + limit )
|
由此可以看出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 分页,重写的方法如下:
01 |
public String getLimitString(String querySelect, int offset, int limit ){
|
02 |
int lastIndexOfOrderBy = getLastIndexOfOrderBy(querySelect);
|
04 |
if (lastIndexOfOrderBy< 0 || querySelect.endsWith( ")" ) || offset== 0 )
|
05 |
return super .getLimitString(querySelect, 0 , limit);
|
08 |
String orderby = querySelect.substring(lastIndexOfOrderBy, querySelect.length());
|
10 |
int indexOfFrom = querySelect.toLowerCase().indexOf( "from" );
|
11 |
String selectFld = querySelect.substring( 0 ,indexOfFrom);
|
13 |
String selectFromTableAndWhere = querySelect.substring(indexOfFrom, lastIndexOfOrderBy);
|
14 |
StringBuffer sql = new StringBuffer(querySelect.length()+ 100 );
|
15 |
sql.append( "select * from (" )
|
17 |
.append( ",ROW_NUMBER() OVER(" ).append(orderby).append( ") as _page_row_num_hb " )
|
18 |
.append(selectFromTableAndWhere).append( " ) temp " )
|
19 |
.append( " where _page_row_num_hb BETWEEN " )
|
20 |
.append(offset+ 1 ).append( " and " ).append(limit);
|
21 |
return sql.toString();
|
让offset参数有效还应重写 public boolean supportsLimitOffset() 方法
public boolean supportsLimitOffset(){
return true;
}
完整的代码如下:
01 |
package com.java1995.dialect;
|
02 |
import org.hibernate.dialect.SQLServerDialect;
|
03 |
public class Java1995SQLServerDialect extends SQLServerDialect {
|
04 |
static int getLastIndexOfOrderBy(String sql){
|
05 |
return sql.toLowerCase().lastIndexOf( "order by " );
|
08 |
public String getLimitString(String querySelect, int offset, int limit ){
|
09 |
int lastIndexOfOrderBy = getLastIndexOfOrderBy(querySelect);
|
11 |
if (lastIndexOfOrderBy< 0 || querySelect.endsWith( ")" ) || offset== 0 )
|
12 |
return super .getLimitString(querySelect, 0 , limit);
|
15 |
String orderby = querySelect.substring(lastIndexOfOrderBy, querySelect.length());
|
17 |
int indexOfFrom = querySelect.toLowerCase().indexOf( "from" );
|
18 |
String selectFld = querySelect.substring( 0 ,indexOfFrom);
|
20 |
String selectFromTableAndWhere = querySelect.substring(indexOfFrom, lastIndexOfOrderBy);
|
21 |
StringBuffer sql = new StringBuffer(querySelect.length()+ 100 );
|
22 |
sql.append( "select * from (" )
|
24 |
.append( ",ROW_NUMBER() OVER(" ).append(orderby).append( ") as _page_row_num_hb " )
|
25 |
.append(selectFromTableAndWhere).append( " ) temp " )
|
26 |
.append( " where _page_row_num_hb BETWEEN " )
|
27 |
.append(offset+ 1 ).append( " and " ).append(limit);
|
28 |
return sql.toString();
|
32 |
public boolean supportsLimitOffset(){
|
最后再 hibernate.cfg.xml 配置 dialect
<property name="dialect">
com.java1995.dialect.Java1995SQLServerDialect
</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
分享到:
相关推荐
5. **新功能支持**:随着Hibernate的进化,新版本的方言也会引入对如批处理操作、存储过程调用等新功能的支持,使开发者能更好地利用达梦数据库的高级特性。 6. **错误修复**:每个版本迭代通常会包含对已知问题的...
总的来说,"hibernate-cglib-repack-2.1_3.jar"是Hibernate框架中不可或缺的一部分,它通过CGLIB库实现了对Java类的动态代理,提供了诸如懒加载、拦截器等高级功能,极大地增强了ORM的灵活性和可扩展性。在实际开发...
这里我们关注的是“达梦Hibernate方言2.0至4.0”,这是一个专为达梦数据库系统(DM)设计的Hibernate方言支持,涵盖了Hibernate框架的多个版本。Hibernate是一个流行的Java对象关系映射(ORM)框架,它允许开发人员...
达梦数据库各版本的hibernate方言包,包含版本 DmDialect-for-hibernate2.0、DmDialect-for-hibernate2.1、DmDialect-for-hibernate3.0、DmDialect-for-hibernate3.1、DmDialect-for-hibernate3.6、DmDialect-for-...
南大通用GBase数据库GBase_Hibernate3.2.3_GA-Dialect_8.3.81.51_build50.1.jar
《Hibernate 3.2.0 参考指南中文版》是Java开发人员的重要参考资料,它详细阐述了Hibernate框架在3.2.0版本中的各种功能和使用方法。Hibernate是一个开源的对象关系映射(ORM)框架,它允许开发者使用面向对象的方式...
Hibernate_3.2.0_Reference_zh_CN.chm Hibernate_3.2.0_Reference_zh_CN.chm
* 达梦8 hibernate方言包对应版本说明 /*************************************** jar包在dialect目录下: 1. DmDialect-for-hibernate2.0.jar 对应 Jdk1.4及以上, hibernate2.0 环境 2. DmDialect-for-hibernate2.1...
总的来说,"hibernate-tutorials_java_hibernate_Eclipse_fallenweg_"这个资源包提供了一个全面的学习路径,涵盖了从安装配置到实际开发的所有关键步骤,对于希望掌握Hibernate的Java开发者来说是一份宝贵的资料。...
`hibernatedialects.txt`可能是一个文本文件,列出了Hibernate支持的所有方言,或者详细描述了方言的用法和特性。而`com`目录可能包含了一些相关的源代码或者类库,其中可能有Hibernate的方言实现,包括...
hibernate方言包
而CGLIB则是一个代码生成库,它允许开发者在运行时动态创建子类,对Java类进行扩展。本文将详细探讨Hibernate-CGLIB的结合使用以及repack.jar在其中的作用。 首先,让我们了解Hibernate。Hibernate是一个开源的ORM...
总结来说,"struts_hibernate_bbs.rar"是一个很好的学习资源,可以帮助开发者提升在Struts和Hibernate集成应用上的技能,从而更好地构建高效、可扩展的Web应用程序,尤其是BBS类型的论坛系统。通过深入研究源代码,...
### Hibernate支持的数据库方言 在Hibernate中,为了适应不同的数据库管理系统(DBMS),它引入了“方言”(Dialect)的概念。方言是Hibernate与特定数据库进行有效沟通的关键组件,负责处理SQL语法差异,确保跨...
2. 支持JPA(Java Persistence API):Hibernate 3.2.0开始全面支持JSR 220的Java Persistence API,使开发人员可以选择使用标准API,同时也提供了更丰富的功能和灵活性。 3. HQL(Hibernate Query Language)增强...
hibernate_@finder mis springmvc springmvc_hiberna" 明确了涉及的技术组件,包括MyBeanUtils(一个自定义工具类库)、Hibernate、@Finder(可能是自定义查询注解)以及两个提及的SpringMVC,暗示了SpringMVC可能有...
标题"DMS.rar_dms_hibernate_myeclipse hibernate_mysql hibernate_struts"表明这是一个与数据库管理系统(DMS)相关的项目,使用了Hibernate ORM框架,MyEclipse作为开发环境,并结合了MySQL数据库和Struts框架。...
### Hibernate C3P0 数据库连接池参数详解 在企业级应用开发中,数据库连接池技术扮演着极其重要的角色,它能显著提高系统的性能并优化资源管理。Hibernate 作为 Java 领域中最流行的 ORM(对象关系映射)框架之一...