首页 > 数据库 >Hibernate处理Oracle的分页,是用rownum。

Hibernate处理Oracle的分页,是用rownum。

时间:2023-06-04 17:05:25浏览次数:59  
标签:Hibernate name cats hibernate Oracle rownum order select SIZE

代码如下:


Java代码

public String getLimitString(String sql, boolean hasOffset);    
{   
  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 <= ?");;   
  }   
  return pagingSelect.toString();;   
}  
[java] view plain copy
public String getLimitString(String sql, boolean hasOffset);   
{  
  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 <= ?");;  
  }  
  return pagingSelect.toString();;  
}  
  public String getLimitString(String sql, boolean hasOffset); 
  {
    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 <= ?");;
    }
    return pagingSelect.toString();;
  }



出错前提


如果这里的sql是不带order by的sql,则查询结果没有任何问题。


但是,如果sql中带有order by,则会引起混乱,即相同记录会出现在不同页中。但是,这种混乱的出现通常是在下面的情况下:


1、纪录数足够多(如果表中有lob字段更好:P)


2、插入记录数大于3页,每页最好10+条记录


3、order by字段至少需要有2个值


4、具备相同order by字段的记录数大于3页


5、插入记录后,最好做删除、修改操作,然后再插入记录。保证记录在磁盘环境中的顺序是无序的。


6、如果满足上述条件,但还没有出现混乱现象,则适当的加大纪录数。


大家测试这种现象,不需要通过hibernate,直接通过sql就可查到。下面有由hibernate生成的sql,以供大家试验:

select * from
  ( select row_.*, rownum rownum_ from
     ( select * from T_TABLE tTable where tTable.field1 order by  tTable.field2 desc ) row_ where rownum <= ?) where rownum_ > ?;

错误原因


之所以出现这样的问题,是和oracle处理ROWNUM的原理相关的。


以下是Oracle参考手册上的一段话:


引用


ROWNUM返回第一次从表中选择时返回的行的序列号。第一行的ROWNUM为1,第二行的为2,依此类推。但要注意, 即使select语句中一条简单的order by都可能会搞乱ROWNUM(因为ROWNUM是排序前分配给各行的)。



解决办法(来自使用手册):


9.3.3. Scrollable iteration

If your JDBC driver supports scrollable ResultSets, the Query interface may be used to obtain a ScrollableResults which allows more flexible navigation of the query results. (Oracle 8.1.6+)


Java代码

Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +   
                            "order by cat.name");;   
ScrollableResults cats = q.scroll();;   
if ( cats.first(); ); {   
  
    // find the first name on each page of an alphabetical list of cats by name   
    firstNamesOfPages = new ArrayList();;   
    do {   
        String name = cats.getString(0);;   
        firstNamesOfPages.add(name);;   
    }   
    while ( cats.scroll(PAGE_SIZE); );;   
  
    // Now get the first page of cats   
    pageOfCats = new ArrayList();;   
    cats.beforeFirst();;   
    int i=0;   
    while( ( PAGE_SIZE > i++ ); && cats.next(); ); pageOfCats.add( cats.get(1); );;   
  
}  
[java] view plain copy
Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +  
                            "order by cat.name");;  
ScrollableResults cats = q.scroll();;  
if ( cats.first(); ); {  
  
    // find the first name on each page of an alphabetical list of cats by name   
    firstNamesOfPages = new ArrayList();;  
    do {  
        String name = cats.getString(0);;  
        firstNamesOfPages.add(name);;  
    }  
    while ( cats.scroll(PAGE_SIZE); );;  
  
    // Now get the first page of cats   
    pageOfCats = new ArrayList();;  
    cats.beforeFirst();;  
    int i=0;  
    while( ( PAGE_SIZE > i++ ); && cats.next(); ); pageOfCats.add( cats.get(1); );;  
  
}  
Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +
                            "order by cat.name");;
ScrollableResults cats = q.scroll();;
if ( cats.first(); ); {
 
    // find the first name on each page of an alphabetical list of cats by name
    firstNamesOfPages = new ArrayList();;
    do {
        String name = cats.getString(0);;
        firstNamesOfPages.add(name);;
    }
    while ( cats.scroll(PAGE_SIZE); );;
 
    // Now get the first page of cats
    pageOfCats = new ArrayList();;
    cats.beforeFirst();;
    int i=0;
    while( ( PAGE_SIZE > i++ ); && cats.next(); ); pageOfCats.add( cats.get(1); );;
 
}



我觉得,如果处理数据库类是一个统一的基类,这种方法不适合用。


11.13 Tips & Tricks


1、Collection elements may be ordered or grouped using a query filter:


Java代码

Collection orderedCollection = s.filter( collection, "order by this.amount" );;   
Collection counts = s.filter( collection, "select this.type, count(this); group by this.type" );;  
[java] view plain copy
Collection orderedCollection = s.filter( collection, "order by this.amount" );;  
Collection counts = s.filter( collection, "select this.type, count(this); group by this.type" );;  
Collection orderedCollection = s.filter( collection, "order by this.amount" );;
Collection counts = s.filter( collection, "select this.type, count(this); group by this.type" );;


2、Collections are pageable by using the Query interface with a filter:


Java代码

Query q = s.createFilter( collection, "" );; // the trivial filter   
q.setMaxResults(PAGE_SIZE);;   
q.setFirstResult(PAGE_SIZE * pageNumber);;   
List page = q.list();;  
[java] view plain copy
Query q = s.createFilter( collection, "" );; // the trivial filter   
q.setMaxResults(PAGE_SIZE);;  
q.setFirstResult(PAGE_SIZE * pageNumber);;  
List page = q.list();;  
Query q = s.createFilter( collection, "" );; // the trivial filter
q.setMaxResults(PAGE_SIZE);;
q.setFirstResult(PAGE_SIZE * pageNumber);;
List page = q.list();;


这种方法的效率有待考察。


所有sql不用ROWNUM的解决办法


如果执行所有SQL都不用ROWNUM,那么最简单的办法如下:


1、派生Dialect类


Java代码

package com.xxx.data.db.hibernate;   
  
import  net.sf.hibernate.dialect.Oracle9Dialect;   
  
public class Oracle9ThunisoftDialect extends Oracle9Dialect   
{   
  public Oracle9ThunisoftDialect();   
  {   
    super();;   
  }   
  
  public boolean supportsLimit();   
  {   
    return false;   
  }   
}  
[java] view plain copy
package com.xxx.data.db.hibernate;  
  
import  net.sf.hibernate.dialect.Oracle9Dialect;  
  
public class Oracle9ThunisoftDialect extends Oracle9Dialect  
{  
  public Oracle9ThunisoftDialect();  
  {  
    super();;  
  }  
  
  public boolean supportsLimit();  
  {  
    return false;  
  }  
}  
package com.xxx.data.db.hibernate;
 
import  net.sf.hibernate.dialect.Oracle9Dialect;
 
public class Oracle9ThunisoftDialect extends Oracle9Dialect
{
  public Oracle9ThunisoftDialect();
  {
    super();;
  }
 
  public boolean supportsLimit();
  {
    return false;
  }
}




2、修改hibernate.cfg.xml配置文件


Java代码

后记

<property name="hibernate.dialect">com.xxx.data.db.hibernate.Oracle9ThunisoftDialect</property>   
  
<!-- oracle 8.1.6+ -->   
<property name="hibernate.jdbc.use_scrollable_resultset">true</property>  
[java] view plain copy
 <property name="hibernate.dialect">com.xxx.data.db.hibernate.Oracle9ThunisoftDialect</property>  
  
<!-- oracle 8.1.6+ -->  
<property name="hibernate.jdbc.use_scrollable_resultset">true</property>  
 <property name="hibernate.dialect">com.xxx.data.db.hibernate.Oracle9ThunisoftDialect</property>
 
<!-- oracle 8.1.6+ -->
<property name="hibernate.jdbc.use_scrollable_resultset">true</property>


通常情况下,这种现象很少出现,因为我们程序中缺省的order by字段的“选择性”都很大,比如缺省以日期时间排序,order by字段很少出现重复。上面的现象基本上不会出现。不过,我们公司在做压力测试的时候,同一日期时间的记录插入了N多条,从而满足了上面提到的5个前提条件,因此出现了同一记录在不同页中出现的现象。


标签:Hibernate,name,cats,hibernate,Oracle,rownum,order,select,SIZE
From: https://blog.51cto.com/u_16112859/6411088

相关文章

  • 基于按annotation的hibernate主键生成策略
    这里讨论代理主键,业务主键(比如说复合键等)这里不讨论。[color=darkblue][b]一、JPA通用策略生成器[/b][/color]通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id,其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法......
  • SpringMVC3.2.x + Hibernate4.2.x + ecache + Spring Security 3.0.5
    这只是部分代码,一些代码可以参考:[url]http://panyongzheng.iteye.com/blog/1871418[/url]SpringSecurity3.1最新配置实例[url它自带的附件也上传。SpringSecurity3十五日研究[url]http://www.blogjava.net/SpartaYew/archive/2013/09/23/350630.html[/......
  • Hibernate Tools源码的使用
    Eclipse中Hibernatetools的安装和使用[url]http://zhoualine.iteye.com/blog/1190141[/url]源码里面有一个很好的格式化类:org.hibernate.tool.hbm2x.[color=darkblue][b]XMLPrettyPrinter[/b][/color]调用publicvoidformatFiles(){ formatXml("......
  • 搭建Hibernate日志-log4jdbc
    官方:[url]https://code.google.com/p/log4jdbc/[/url]log4jdbc分析sql性能[url]http://hongliangpan.iteye.com/blog/1088398[/url]xml配置方法:log4jdbc日志框架介绍[url]http://blog.sina.com.cn/s/blog_57769b7b0101m1il.html[/url][url]http://xia......
  • Hibernate和 OsCache的使用
    下载地址:[url]http://java.net/downloads/oscache/[/url]oscache这个jar里面的jms架包已经无法下载了。那么我就在网上自己下载了一个jms.jar安装到本地的仓库中去,就ok了。进入安装maven的目录bin中,执行如下命令:[i][color=blue]mvninstall:install-file......
  • hibernate中自定义主键生成器
    自定义hibernate主键生成机制[url]http://walle1027.iteye.com/blog/1114824[/url]org.hibernate.id.MultipleHiLoPerTableGenerator主键生成器[url]http://suzefeng8806.iteye.com/blog/923511[/url][url]http://zhongrf.iteye.com/blog/972303[/url]......
  • Oracle统计信息之NO_INVALIDATE参数
    文档课题:Oracle统计信息之NO_INVALIDATE参数.1、理论知识Oracle统计信息对于CBO至关重要.RBO建立在数据结构的基础上,DDL结构、约束会将SQL语句分为不同的成本结构等级.而CBO是在数据结构的基础上加入数据表细粒度信息,将成本结构细化为成本cost值.相对于数据表的DDL结构,统计信息反......
  • hibernate------hql总结
    第14章HQL:Hibernate查询语言[url]http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/queryhql.html[/url][url]http://kuangbaoxu.iteye.com/blog/193076[/url][color=red][b]1.查询整个映射对象所有字段[/b][/color]//直接from查询出来的是一......
  • Hibernate性能调优,优化
    Hibernate优化_Hibernate性能优化_Hibernate优化方案(上):[url]http://xiexiejiao.cn/hibernate/hibernate-performance-optimization-a.html[/url]Hibernate优化_Hibernate性能优化_Hibernate优化方案(下):[url]http://xiexiejiao.cn/hibernate/hibernate-performance-optimizati......
  • Hibernate Tools生成Hibernate Mapping文件及PO类
    [color=red][b]本文参考[/b][/color]:HowToGenerateHibernateMappingFiles&AnnotationWithHibernateTools[url]http://www.mkyong.com/hibernate/how-to-generate-code-with-hibernate-tools/[/url]eclipse利用HibernateTools生成HibernateMap......