天行健,君子以自強不息

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            12 Posts :: 0 Stories :: 2 Comments :: 0 Trackbacks
          由于Hibernate的強大,我們對數據庫的操作也省心了不少,但是hibernate自動生成的一系列sql,也許并不是如我們所想象的那樣,所以,我們又多了一些本來不要操心的事情。比如在一對多的查詢中,就有可能存在查詢記錄重復的問題。

          有如下兩個對象:文章和關鍵字。它們之間的關系,很明顯,是一對多的關系,一個文章可以有很多的關鍵字。

          假設有文章atricleA、articleB,articleA有關鍵字keyword1、keyword2,articleB有關鍵字keyword3、keyword4。
          我們現在想查詢含有關鍵字keyword1或者keyword3的所有文章列表,正確的結果應該是articleA和articleB兩條記錄。然而,如果使用hibernate不當,有可能你得到的是articleA、articleA、articleB、articleB四條記錄,其中兩條是重復的。

          這是怎么發生的呢?
          如果我們這樣使用hibernate來實現這個查詢:
          StringBuffer queryString = new StringBuffer();
          queryString.append(
          "from ArticleData where keyword=? or keyword=?");

          String[] param 
          = new String[]{"keyword1","keyword3"};

          Query query 
          = session.createQuery(queryString );

          query.list();

          看看hibernate給我們生成的sql語句:
          select article_table_.*
          from
           articletable article_table_,keywordtable keyword_table1_ ,keywordtable keyword_table2_
          where article_table_.id=keyword_table1_.articleid and article_table_.id=keyword_table2_.articleid
                    and
           (keyword_table1_.name='keyword1' or keyword_table2_.name='keyword3')
          根據這個sql,我們可以得出,滿足where約束的有如下幾個組合:
          articleA   keyword1  keyword1
          articleA   keyword1  keyword2
          aritcleB   keyword3  keyword3
          articleB   keyword3  keyword4
          正是我們之前所說得到的錯誤結果。

          仔細分析這個sql,其實問題就出在hibernate生成sql的時候,對同一個表keywordtable查詢了兩次(在from中出現兩次),因此就有了組合的可能性,可以想見,如果再多幾個需要查詢的關鍵字,同一個記錄重復的次數會更多。

          其實,要正確的破解這個問題,我們可以自己寫sql語句,使用hibernate同樣支持的原生sql查詢,不使用hibernate的hql查詢。

          hibernate在給我們帶來很多便利性的同時,也給我們多多少少帶來了一些麻煩,而這些問題的定位成本可能也會很高。要使用好工具,就要知道工具的優缺點,尤其是缺點要有足夠的風險控制。

          革命尚未成功,同志仍需努力!

          posted on 2008-04-22 00:14 yill 閱讀(3594) 評論(1)  編輯  收藏

          Feedback

          # re: Hibernate 一對多查詢的記錄重復問題 2012-04-29 22:57
          直接用select distinct 對象名 +后面的一堆就可以了  回復  更多評論
            


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


          網站導航:
           
          主站蜘蛛池模板: 枣庄市| 涞源县| 揭阳市| 澄江县| 石棉县| 明水县| 武定县| 涞源县| 博爱县| 衡阳市| 萨嘎县| 抚顺市| 奉贤区| 都昌县| 郴州市| 赤水市| 布尔津县| 克山县| 泉州市| 昆山市| 鄂伦春自治旗| 宣恩县| 广昌县| 济源市| 昌邑市| 成安县| 邢台县| 大英县| 安义县| 墨玉县| 云浮市| 泰州市| 宜兰市| 镇江市| 普定县| 民勤县| 嘉善县| 金溪县| 宜城市| 宣威市| 宁波市|