天行健,君子以自強不息

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


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


          網站導航:
           
          主站蜘蛛池模板: 稻城县| 资源县| 应城市| 邯郸县| 石河子市| 屏山县| 潼关县| 临猗县| 郴州市| 商南县| 石河子市| 门头沟区| 凤阳县| 株洲县| 越西县| 疏附县| 闽侯县| 靖江市| 阿拉善右旗| 钟山县| 郴州市| 木兰县| 竹溪县| 晋城| 十堰市| 饶阳县| 龙门县| 盐山县| 屯昌县| 无极县| 荣昌县| 嵊州市| 宁远县| 区。| 遵化市| 彰武县| 昌图县| 凤阳县| 芦溪县| 旌德县| 林西县|