與Java相伴的日子
          相識,相知,相戀,到相守......我的日子因你的到來而充實,我的日子因你的存在而多姿!
          posts - 4,comments - 31,trackbacks - 0

          ?

          ??????? 我的一個項目使用了Hibernate3操作Oracle9i數據庫,遇到一個很奇怪的問題,即在按某些使用了聚合函數的值的升序排序后,翻頁到一定頁數(通常是3或5)以后,顯示的內容不會變化,即出現不是期望的查詢結果.
          ??????? 剛開始仔細排查,找不出原因.后來通過查Hibernate 包中的Oracle9Dialect及OracleDialect的源碼,將Dialect換成 OracleDialect后問題解決.
          ?????? 但是,問題雖解決了,根源何在呢?為什么Oracle9卻要用到OracleDialect(源碼注解中說這是兼容Oracle8i)的才能解決問題呢?!
          ???? ?查看源碼,發現兩者取得分頁查詢字符串的方式是有點區別的(在 getlimitString()方法中).

          ?? ?在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();
          ?}



          ??????? 在OracleDialect中:

          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_?<=???and?rownum_?>?? " );
          ??}

          ??
          else ? {
          ???pagingSelect.append(
          " ?)?where?rownum?<=?? " );
          ??}


          ??
          if ?(isForUpdate)?pagingSelect.append( " ?for?update " );
          ??
          ??
          return ?pagingSelect.toString();
          ?}



          ??????? 兩者的區別主要在于,前者:
          row_ where rownum <= ?) where rownum_ > ?
          后者:
          where rownum_ <= ? and rownum_ > ?

          我模擬了我的出問題的查詢,使用前者問題重現,使用后者不出問題.
          另外是,只在升序排序時才出問題,降序則不會.

          我的語句分別如下:
          *************************************************************************
          第一種:

          select ? * ? from ?(

          ?
          select ?rownum?row_num?,t. * ?? from (
          ?
          select ? Sum (b.disp_Count)?,? Sum (b.click_Count)?,?
          ???
          Sum (b.total_Price)?,? Sum (b.return_Cost)?,?
          ???
          avg (b.rank)??,?b.sta_Date???,?b.keyword_Name??,?
          ???b.union_Name??
          ???
          from ?Bid_Report?b??
          ????????
          where ??(b.sta_Date? = ' 20051129 ' )??
          ??????????
          group ? by ??b.sta_Date,??b.keyword_Name,??b.union_Name?
          ??????????
          order ? by ?? Sum (b.click_Count),?b.sta_Date?
          ????????)?t??
          where ?rownum <= 60
          ??)?
          where ?row_num? > ? 40


          (在Hibernate3中,Oracle9Dialect的getLimitString()方法采取類似實現方式)

          第二種:

          select ? * ? from ?(

          ?
          select ?rownum?row_num?,t. * ?? from (
          ?
          select ? Sum (b.disp_Count)?,? Sum (b.click_Count)?,?
          ???
          Sum (b.total_Price)?,? Sum (b.return_Cost)?,?
          ???
          avg (b.rank)??,?b.sta_Date???,?b.keyword_Name??,?
          ???b.union_Name??
          ???
          from ?Bid_Report?b??
          ????????
          where ??(b.sta_Date? = ' 20051129 ' )??
          ??????????
          group ? by ??b.sta_Date,??b.keyword_Name,??b.union_Name?
          ??????????
          order ? by ?? Sum (b.click_Count),?b.sta_Date??
          ????????)?t??
          ??)?
          where ?row_num? <= 60 ? and ?row_num > 40

          (在Hibernate3中,OracleDialect的getLimitString()方法采取類似實現方式)

          **********************************************************************

          現在,問題是:為什么采取后者就可以解決問題了呢?這是不是Oracle9Dialect的一個bug呢?!
          哪位高手能給我詳析,感激不盡!!!!

          posted on 2005-12-30 09:41 南一郎 閱讀(1355) 評論(0)  編輯  收藏

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


          網站導航:
           
          主站蜘蛛池模板: 上杭县| 昌都县| 扶余县| 改则县| 扎兰屯市| 平原县| 城口县| 大新县| 竹山县| 池州市| 梨树县| 洛川县| 淳化县| 钟祥市| 包头市| 呼图壁县| 巩义市| 柯坪县| 宁阳县| 新绛县| 上犹县| 石柱| 巩义市| 三亚市| 久治县| 二连浩特市| 玛曲县| 克拉玛依市| 宁海县| 建宁县| 永修县| 进贤县| 内黄县| 衡南县| 电白县| 郴州市| 东港市| 都安| 双牌县| 泉州市| 湟源县|