隨筆-10  評論-10  文章-0  trackbacks-0
              請問,如何使用Hibernte進行分頁????
          posted on 2007-04-23 21:34 細雨游風 閱讀(255) 評論(2)  編輯  收藏

          評論:
          # re: 有沒哪位大哥大姐幫幫我? 2007-04-26 18:06 | 123
          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類的divpareQueryStatement方法中,對分頁支持的代碼在這一段中可以發現:
          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()移動的辦法。這樣既兼顧了查詢分頁的性能,同時又保證了代碼在不同的數據庫之間的可移植性。
            回復  更多評論
            
          # re: 有沒哪位大哥大姐幫幫我? 2007-04-26 20:16 | 細雨游風
          嗯 很詳細 謝謝你~~!  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 获嘉县| 凤翔县| 海淀区| 股票| 抚远县| 新河县| 海兴县| 清苑县| 阜城县| 财经| 银川市| 阿克陶县| 察隅县| 沈丘县| 策勒县| 中卫市| 砀山县| 汉中市| 青岛市| 福海县| 谢通门县| 铁岭市| 汉源县| 顺义区| 闽侯县| 富顺县| 宕昌县| 琼中| 灵丘县| 泗洪县| 孟州市| 布拖县| 筠连县| 宁陕县| 陆良县| 宁乡县| 霍邱县| 阿鲁科尔沁旗| 高唐县| 合肥市| 响水县|