隨筆-10  評(píng)論-10  文章-0  trackbacks-0
              請(qǐng)問(wèn),如何使用Hibernte進(jìn)行分頁(yè)????
          posted on 2007-04-23 21:34 細(xì)雨游風(fēng) 閱讀(258) 評(píng)論(2)  編輯  收藏

          評(píng)論:
          # re: 有沒(méi)哪位大哥大姐幫幫我? 2007-04-26 18:06 | 123
          Hibernate提供了一個(gè)支持跨系統(tǒng)的分頁(yè)機(jī)制,這樣無(wú)論底層是什么樣的數(shù)據(jù)庫(kù)都能用統(tǒng)一的接口進(jìn)行分頁(yè)操作。比如下面的代碼就是從第500條開(kāi)始取出100條記錄:
          Query q = session.createQuery("from FooBar as f");
          q.setFirstResult(500);
          q.setMaxResults(100);
          List l = q.list();
          那么Hibernate底層如何實(shí)現(xiàn)分頁(yè)的呢?Hibernate根據(jù)Query拼裝SQL語(yǔ)句的地方是在org.hibernate.loader.Loader類的divpareQueryStatement方法中,對(duì)分頁(yè)支持的代碼在這一段中可以發(fā)現(xiàn):
          if (useLimit)
          {
          sql = dialect.getLimitString(
          sql.trim(), //use of trim() here is ugly?
          useOffset ? getFirstRow(selection) : 0,
          getMaxOrLimit(selection, dialect)
          );
          }
          此處調(diào)用Dialect的getLimitString方法來(lái)得到不同平臺(tái)的分頁(yè)語(yǔ)句。
          在MySQLDialect中是如下實(shí)現(xiàn)getLimitString方法的:
          public String getLimitString(String sql, boolean hasOffset)
          {
          return new StringBuffer( sql.length()+20 )
          .append(sql)
          .append( hasOffset ? " limit ?, ?" : " limit ?")
          .toString();
          }
          這是MySQL的專用分頁(yè)語(yǔ)句,再來(lái)看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層的查詢語(yǔ)句結(jié)合rownum來(lái)實(shí)現(xiàn)分頁(yè),這在Oracle上是最好的方式,因?yàn)槿绻皇且粚踊蛘邇蓪拥牟樵冋Z(yǔ)句的rownum不能支持order by。
          此外Interbase,PostgreSQL,HSQL等也在語(yǔ)法級(jí)別上支持分頁(yè),具體實(shí)現(xiàn)可以查看相應(yīng)的Dialect實(shí)現(xiàn)。如果數(shù)據(jù)庫(kù)不支持分頁(yè)的SQL語(yǔ)句,那么如果數(shù)據(jù)庫(kù)支持可滾動(dòng)游標(biāo),那么Hibernate就會(huì)采使用ResultSet的absolute方法直接移到查詢起點(diǎn);否則使用循環(huán)語(yǔ)句,通過(guò)rs.next一步步移動(dòng)到要查詢的數(shù)據(jù)處:
          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();
          }
          }

          可見(jiàn)使用Hibernate,在進(jìn)行查詢分頁(yè)的操作上,是具有非常大的靈活性,Hibernate會(huì)首先嘗試用特定數(shù)據(jù)庫(kù)的分頁(yè)sql,如果沒(méi)用,再嘗試Scrollable,如果不支持Scrollable再采用rset.next()移動(dòng)的辦法。這樣既兼顧了查詢分頁(yè)的性能,同時(shí)又保證了代碼在不同的數(shù)據(jù)庫(kù)之間的可移植性。
            回復(fù)  更多評(píng)論
            
          # re: 有沒(méi)哪位大哥大姐幫幫我? 2007-04-26 20:16 | 細(xì)雨游風(fēng)
          嗯 很詳細(xì) 謝謝你~~!  回復(fù)  更多評(píng)論
            

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


          網(wǎng)站導(dǎo)航:
           
          <2007年4月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(3)

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 博爱县| 禄丰县| 门源| 黄石市| 松滋市| 东台市| 布尔津县| 荃湾区| 九江市| 汉川市| 淅川县| 司法| 大足县| 台中市| 仙居县| 全椒县| 诸城市| 鄂托克旗| 定陶县| 铅山县| 池州市| 长海县| 敖汉旗| 阿合奇县| 普格县| 禄丰县| 茶陵县| 丰城市| 青海省| 张家口市| 鹿泉市| 芦山县| 南靖县| 太保市| 尤溪县| 上蔡县| 历史| 长沙市| 紫金县| 密云县| 滦南县|