<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Hibernate實(shí)現(xiàn)分頁查詢的原理

    一直為分頁查詢頭痛,Google了一下搜到這篇好文章。Hibernate從底層實(shí)現(xiàn)各種數(shù)據(jù)庫的分頁查詢,并且將這種數(shù)據(jù)庫間的差異用統(tǒng)一的方法封裝起來了。不過最好還是了解一下原理,也好自己寫寫簡單的分頁。畢竟并不是什么時(shí)候都能用Hibernate的。
    Hibernate 可以實(shí)現(xiàn)分頁查詢,例如:
    從第2萬條開始取出100條記錄
    Query q = session.createQuery("from Cat as c");
    q.setFirstResult(
    20000);
    q.setMaxResults(
    100);
    List l 
    = q.list();

    那么Hibernate底層如何實(shí)現(xiàn)分頁的呢?實(shí)際上Hibernate的查詢定義在net.sf.hibernate.loader.Loader這個(gè)類里面,仔細(xì)閱讀該類代碼,就可以把問題徹底搞清楚。Hibernate2.0.3的Loader源代碼第480行以下:

    if (useLimit) sql = dialect.getLimitString(sql);
    PreparedStatement st 
    = session.getBatcher().prepareQueryStatement(sql, scrollable);

    如果相應(yīng)的數(shù)據(jù)庫定義了限定查詢記錄的sql語句,那么直接使用特定數(shù)據(jù)庫的sql語句。然后來看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();   
    }  
    這是MySQL的專用分頁語句,再來看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();   
    }

    Oracle采用嵌套3層的查詢語句結(jié)合rownum來實(shí)現(xiàn)分頁,這在Oracle上是最快的方式,如果只是一層或者兩層的查詢語句的rownum不能支持order by。

    除此之外,Interbase,PostgreSQL,HSQL也支持分頁的sql語句,在相應(yīng)的Dialect里面,大家自行參考。

    如果數(shù)據(jù)庫不支持分頁的SQL語句,那么根據(jù)在配置文件里面
    #hibernate.jdbc.use_scrollable_resultset true
    默認(rèn)是true,如果你不指定為false,那么Hibernate會(huì)使用JDBC2.0的scrollable result來實(shí)現(xiàn)分頁,看Loader第430行以下:

    if ( session.getFactory().useScrollableResultSets() ) {   
      
    // 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();   
    }

    如果支持scrollable result,使用ResultSet的absolute方法直接移到查詢起點(diǎn),如果不支持的話,使用循環(huán)語句,rs.next一點(diǎn)點(diǎn)的移過去。

    可見使用Hibernate,在進(jìn)行查詢分頁的操作上,是具有非常大的靈活性,Hibernate會(huì)首先嘗試用特定數(shù)據(jù)庫的分頁sql,如果沒用,再嘗試Scrollable,如果不行,最后采用rset.next()移動(dòng)的辦法。

    在查詢分頁代碼中使用Hibernate的一大好處是,既兼顧了查詢分頁的性能,同時(shí)又保證了代碼在不同的數(shù)據(jù)庫之間的可移植性。

    Oracle的這種實(shí)現(xiàn)如果有order by子句依然有問題。某些時(shí)候會(huì)導(dǎo)致翻頁有記錄重復(fù)或者遺失,很難找到規(guī)律,非常奇怪。

    后來去google了一下,有Oracle專家說需要order by的時(shí)候必須帶上unique的字段,例如主鍵或者rowid等。

    另外,在使用這種采用rownum的查詢時(shí),盡管速度相對(duì)比較快,但是后臺(tái)Oracle在內(nèi)存和CPU的消耗上會(huì)增加許多。其實(shí)除非結(jié)果集非常龐大(幾萬以上),并且必須翻倒很后面(skip的記錄很多),采用ResultSet.absolute方法性能還可以,并沒有數(shù)量級(jí)上的差別。

    posted on 2007-08-24 11:01 靈魂守護(hù)者 閱讀(400) 評(píng)論(0)  編輯  收藏 所屬分類: Hibernate


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    留言簿(1)

    文章分類(2)

    文章檔案(4)

    收藏夾(9)

    搜索

    最新評(píng)論

    主站蜘蛛池模板: 亚洲自偷自拍另类图片二区| 一级日本高清视频免费观看| 亚洲精品天堂无码中文字幕| 免费无码婬片aaa直播表情| 国产好大好硬好爽免费不卡| 国产亚洲精久久久久久无码| 久久久久久毛片免费看| 在线免费不卡视频| 亚洲色大成网站www久久九| 成人毛片视频免费网站观看| 亚洲小说图区综合在线| 啦啦啦在线免费视频| 亚洲欧美日韩综合久久久久| 国产片免费在线观看| 特级毛片免费播放| 日韩毛片免费在线观看| 亚洲特级aaaaaa毛片| 美女裸身网站免费看免费网站 | 在线观看av永久免费| 77777亚洲午夜久久多人| 成年免费a级毛片免费看无码| 亚洲中文字幕在线观看| 久久午夜伦鲁片免费无码| 亚洲婷婷综合色高清在线| 国内精品免费视频自在线| 美女免费精品高清毛片在线视| 狠狠综合久久综合88亚洲| 97在线视频免费播放| 久久久久亚洲AV无码专区首| 在线观看www日本免费网站| 亚洲av之男人的天堂网站 | 成人免费视频小说| 免费激情网站国产高清第一页| 亚洲熟妇无码AV在线播放| 91久久成人免费| 国产亚洲美女精品久久| 亚洲AV无码不卡无码| 成人免费看片又大又黄| 最近更新免费中文字幕大全| 亚洲乱码卡三乱码新区| 4hu四虎最新免费地址|