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

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

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

    如鵬網 大學生計算機學習社區

    CowNew開源團隊

    http://www.cownew.com 郵件請聯系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

    ?分頁在任何系統中都是非常頭疼的事情,有的數據庫在語法上支持分頁,而有的數據庫則需要使用可滾動游標來實現,并且在不支持可滾動游標的系統上只能使用單向游標逐步接近要取得的數據。
    ?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()移動的辦法。這樣既兼顧了查詢分頁的性能,同時又保證了代碼在不同的數據庫之間的可移植性。

    posted on 2007-03-06 09:22 CowNew開源團隊 閱讀(681) 評論(0)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 成年18网站免费视频网站| 国产亚洲女在线线精品| 一级毛片直播亚洲| 最好看的中文字幕2019免费| 一本到卡二卡三卡免费高 | 一级午夜a毛片免费视频| 亚洲男人天堂2018av| 亚洲激情视频在线观看| 亚洲人成网站在线观看青青| 日本xxwwxxww在线视频免费| 91免费国产在线观看| 久久青草免费91线频观看站街| 一级特级女人18毛片免费视频| 亚洲欧美国产国产一区二区三区| 亚洲综合在线成人一区| 亚洲av综合av一区| 美女羞羞视频免费网站| 久久夜色精品国产嚕嚕亚洲av| 亚洲精品国产高清不卡在线| 午夜电影免费观看| 无码人妻一区二区三区免费手机 | 日韩亚洲国产高清免费视频| 久久精品国产大片免费观看| 最近更新免费中文字幕大全| 一个人看的www免费高清| 无码天堂亚洲国产AV| 亚洲av无码专区在线电影天堂| 狠狠色伊人亚洲综合网站色 | 成人女人A级毛片免费软件| 黄+色+性+人免费| 免费福利视频导航| aⅴ在线免费观看| 成人免费黄色网址| 国产免费女女脚奴视频网| 中文免费观看视频网站| **实干一级毛片aa免费| 中国人xxxxx69免费视频| 亚洲成人在线免费观看| 69天堂人成无码麻豆免费视频| 99久久99久久精品免费看蜜桃| 久久天天躁狠狠躁夜夜免费观看|