Hibernate 分页

标签: hibernate 数据库 sql postgresql oracle query
1744人阅读 评论(0) 收藏 举报
分类:
分页在任何系统中都是非常头疼的事情,有的数据库在语法上支持分页,而有的数据库则需要使用可滚动游标来实现,并且在不支持可滚动游标的系统上只能使用单向游标逐步接近要取得的数据。
 Hibernate提供了一个支持跨系统的分页机制,这样无论底层是什么样的数据库都能用统一的接口进行分页操作。比如下面的代码就是从第500条开始取出100条记录: 
Query q = session.createQuery("from FooBar as f"); 
q.setFirstResult(500); 
q.setMaxResults(100); 
List l = q.list(); 
那么Hibernate底层如何实现分页的呢?Hibernate根据Query拼装SQL语句的地方是在org.hibernate.loader.Loader类的prepareQueryStatement方法中,对分页支持的代码在这一段中可以发现:
if (useLimit) 
{
sql = dialect.getLimitString( 
     sql.trim(), //use of trim() here is ugly?
     useOffset ? getFirstRow(selection) : 0, 
     getMaxOrLimit(selection, dialect) 
    );
 }
 此处调用Dialect的getLimitString方法来得到不同平台的分页语句。
在MySQLDialect中是如下实现getLimitString方法的:
public String getLimitString(String sql, boolean hasOffset) 
{
return new StringBuffer( sql.length()+20 )
.append(sql)
.append( hasOffset ? " limit ?, ?" : " limit ?")
.toString();
}
 这是MySQL的专用分页语句,再来看Oracle9Dialect:
 public String getLimitString(String sql, boolean hasOffset) {
  
  sql = sql.trim();
  boolean isForUpdate = false;
  if ( sql.toLowerCase().endsWith(" for update") ) {
   sql = 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();
 } 
Oracle采用嵌套3层的查询语句结合rownum来实现分页,这在Oracle上是最好的方式,因为如果只是一层或者两层的查询语句的rownum不能支持order by。
此 外Interbase,PostgreSQL,HSQL等也在语法级别上支持分页,具体实现可以查看相应的Dialect实现。如果数据库不支持分页的 SQL语句,那么如果数据库支持可滚动游标,那么Hibernate就会采使用ResultSet的absolute方法直接移到查询起点;否则使用循环 语句,通过rs.next一步步移动到要查询的数据处: 
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,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试 Scrollable,如果不支持Scrollable再采用rset.next()移动的办法。这样既兼顾了查询分页的性能,同时又保证了代码在不同的 数据库之间的可移植性。
查看评论

用户Hibernate写的一个分页

1.创建一个分页组建PageModel.javapackage com.zsw.util;import java.util.List;/** * 分页组建 * @author zsw * 时间:200...
  • sz_bdqn
  • sz_bdqn
  • 2009-02-13 11:09:00
  • 2022

Hibernate 分页的两种方式

第一种:hql分页(不推荐)需要手动关闭session连接//PageBean.java @SuppressWarnings("hiding") public class PageBean { ...
  • yangfan5314
  • yangfan5314
  • 2017-06-23 16:51:58
  • 1352

Hibernate第十篇【Hibernate查询详解、分页查询】

前言在Hibernate的第二篇中只是简单地说了Hibernate的几种查询方式….到目前为止,我们都是使用一些简单的主键查询阿…使用HQL查询所有的数据….本博文主要讲解Hibernate的查询操作...
  • hon_3y
  • hon_3y
  • 2017-05-08 15:58:37
  • 8139

Hibernate分页原理简单分析

通常使用的Hibernate查询是三种:hql查询,QBC查询和QBE查询。    1、QBE(Qurey By Example)检索方式         QBE是最简单的,但...
  • hll174
  • hll174
  • 2016-03-17 18:29:59
  • 762

hibernate分页工具类

hibernate分页工具类,附带具体的分页方法
  • u013614451
  • u013614451
  • 2014-05-10 17:28:22
  • 1457

最优化最灵活的Hibernate分页_hql实现

page.java(全类代码) package com.yongle.web.utils; import java.util.ArrayList; import java.util.List; ...
  • lzgame
  • lzgame
  • 2011-09-05 11:21:25
  • 1658

Hibernate的分页技术

Hibernate的分页技术是透明的,,你理解最好,不能理解先用着呗。。  说白了就是查询语句中你不用写上一堆的分页语句了,Hibernate已经实现了,但最终的查询跟手工的查询没两样,oracle...
  • you_off3
  • you_off3
  • 2012-05-11 14:27:16
  • 4964

实现了hibernate的简单的分页了。其实很简单(一)

今天终于实现了hibernate实现分页了。。把oksonic的SSH的例子做了增加,实现了查询的分页。同时现在也把srtuts + spring + hibernate  结合的实现方法重新复习了一...
  • xdy3008
  • xdy3008
  • 2006-08-10 16:05:00
  • 1106

浅论Hibernate分页的“真”与“假”

今天有学员问我:“hibernate是真分页么?我今天看了一些帖子,好像是真分页。……”这个问题不能简单地用“真”或“假”来回答。Hibernate分页的“真”与“假”,取决于所指定的方言(Diale...
  • accp206
  • accp206
  • 2008-05-28 18:29:00
  • 2585

spring+hibernate+mysql 分页

最近在做毕业设计,想着每天记录下做了什么吧,这样也方便看看进度。接下来先总结下前几天做的东西,有些是以前就记录好的,这里copy下。 这个是15号做的笔记,我不大习惯做笔记,但是发现这个习惯真的得好...
  • Shangdyu
  • Shangdyu
  • 2011-11-17 09:44:35
  • 6187
    公告
    个人资料
    等级:
    访问量: 602万+
    积分: 6万+
    排名: 43
    最新评论