浅析Hibernate分页管理

开发 后端
Hibernate中,抽象类org.hibernate.dialect.Dialect指定了所有底层数据库的对外统一接口,通过针对不同数据库提供相应的Dialect实现,数据库之间的差异性得以消除,从而为上层机制提供了透明的、数据库无关的存储层基础。

本文向大家介绍Hibernate分页,可能好多人还不了解Hibernate分页,没有关系,看完本文你肯定有不少收获,希望本文能教会你更多东西。

Hibernate中,通过对不同数据库的统一接口设计,实现了透明化、通用化的分页实现机制。

通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围,如:

Criteria criteria = session.createCriteria(TUser.class);  
criteria.add(Expression.eq("age", "20"));  
//从检索结果中获取第100条记录开始的20条记录  
criteria.setFirstResult(100);  
criteria.setFetchSize(20);  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

通过Query.setFirstResult和Query.setMaxResults方法也可以设定分页范围,如:

Query query = session.createQuery("from TUser");  
query.setFirstResult(100);  
query.setMaxResults(20);  // query.setFetchSize(20);  
List list = query.list();  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

Hibernate中,抽象类org.hibernate.dialect.Dialect指定了所有底层数据库的对外统一接口,通过针对不同数据库提供相应的Dialect实现,数据库之间的差异性得以消除,从而为上层机制提供了透明的、数据库无关的存储层基础。对于分页机制而言,Dialect中定义了一个方法如下:

/**  
  * Add a LIMIT clause to the given SQL SELECT  
  *  
  * @return the modified SQL  
  */  
 public String getLimitString(String querySelect, boolean hasOffset) {  
  throw new UnsupportedOperationException( "paged queries not supported" );  
 }  
 
 public String getLimitString(String querySelect, int offset, int limit) {  
  return getLimitString( querySelect, offset>0 );  
 }  
 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

此方法用于在现有Select语句基础上,根据各个数据库自身特性,构造对应的记录返回限定子句。如MySQL中对应的记录限定子句为Limit,Oracle中,通过rownum子句实现。MySQLDialect中的getLimitString实现:

public String getLimitString(String sql, boolean hasOffset) {  
  return new StringBuffer( sql.length()+20 )  
   .append(sql)  
   .append( hasOffset ? " limit ?, ?" : " limit ?")  
   .toString();  
 }  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

MySQLDialect.getLimitString方法的实现实际上是在给定的Select语句后追加MySQL所提供的专有SQL子句limit来实现。

Oracle9Dialect中的getLimitString实现:

public String getLimitString(String sql, boolean hasOffset) {  
    
  sqlsql = sql.trim();  
  boolean isForUpdate = false;  
  if ( sql.toLowerCase().endsWith(" for update") ) {  
   sqlsql = sql.substring( 0, sql.length()-11 );  
   isForUpdate = true;  
  }  
    
  StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );  
  if (hasOffset) {  
   pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");  
  }  
  else {  
   pagingSelect.append("select * from ( ");  
  }  
  pagingSelect.append(sql);  
  if (hasOffset) {  
   pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");  
  }  
  else {  
   pagingSelect.append(" ) where rownum <= ?");  
  }  
 
  if ( isForUpdate ) {  
   pagingSelect.append( " for update" );  
  }  
    
  return pagingSelect.toString();  
 }  
 
  • 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.

通过Oracle特有的rownum子句来实现数据部分的读取。SQLServerDialect中的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();  
 }  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

通过SQLServer特有的top子句实现。HSQLDialect中的getLimitString实现:

public String getLimitString(String sql, boolean hasOffset) {  
  return new StringBuffer( sql.length() + 10 )  
    .append( sql )  
    .insert( sql.toLowerCase().indexOf( "select" ) + 6, hasOffset ? " limit ? ?" : " top ?" )  
    .toString();  
 }  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.


大多数主流数据库都提供了数据部分读取机制,而对于某些没有提供相应机制的数据库而言,Hibernate也通过其他途径实现了分页,如通过Scrollable ResultSet,如果JDBC不支持Scrollable ResultSet,Hibernate也会通过ResultSet的next方法进行记录定位。Hibernate通过底层对分页机制的良好封装,使得开发人员无需关心数据分页的细节实现,将数据逻辑和存储逻辑分离开来,在提高生产效率的同时,也大大加强了系统在不同数据库平台之间的可移植性。

【编辑推荐】

  1. 如何解决Struts Hibernate的整合问题
  2. 对Hibernate中get()与load()不同点分析
  3. Struts-Spring-Hibernate案例
  4. 简述Hibernate配置连接池
  5. 对Hibernate中get()与load()不同点分析

 

责任编辑:仲衡 来源: baidu
相关推荐

2009-09-21 18:13:11

Hibernate S

2009-09-28 17:23:51

Hibernate E

2009-09-22 13:09:06

Hibernateorm框架

2009-09-24 11:41:46

Hibernate延迟

2009-09-21 17:23:49

Hibernate使用

2009-09-21 12:50:34

Hibernate架构

2009-09-23 17:28:55

Hibernate C

2009-09-22 17:32:38

Hibernate A

2009-09-22 10:23:15

Hibernate配置

2009-06-11 14:40:59

Hibernate分页Hibernate查询

2009-06-17 14:55:26

Hibernate数据

2009-09-24 10:07:21

Hibernate M

2009-09-23 11:07:11

Hibernate基础

2009-09-23 13:26:10

Hibernate对象

2009-09-29 16:11:45

Hibernate实现

2009-09-25 10:49:25

Hibernate加载

2009-06-25 17:24:06

Hibernate主键

2009-09-22 15:26:30

Hibernate多表

2009-09-24 13:39:06

Hibernate VHibernate P

2009-09-22 14:44:18

Hibernate.c
点赞
收藏

51CTO技术栈公众号