天行健,君子以自強不息

          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 對象名 +后面的一堆就可以了  回復  更多評論
            


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


          網站導航:
           
          主站蜘蛛池模板: 梓潼县| 油尖旺区| 淮北市| 大姚县| 牟定县| 迁西县| 防城港市| 盱眙县| 吴川市| 贞丰县| 乌拉特后旗| 宜兴市| 孙吴县| 安义县| 元朗区| 江城| 沿河| 宜兴市| 托克托县| 本溪市| 华亭县| 大邑县| 金溪县| 乌鲁木齐市| 陕西省| 宁南县| 福鼎市| 正安县| 仙居县| 裕民县| 七台河市| 锦屏县| 英吉沙县| 庐江县| 新化县| 台北市| 共和县| 山丹县| 车险| 志丹县| 崇信县|