由于Hibernate的強大,我們對數據庫的操作也省心了不少,但是hibernate自動生成的一系列sql,也許并不是如我們所想象的那樣,所以,我們又多了一些本來不要操心的事情。比如在一對多的查詢中,就有可能存在查詢記錄重復的問題。
有如下兩個對象:文章和關鍵字。它們之間的關系,很明顯,是一對多的關系,一個文章可以有很多的關鍵字。
假設有文章atricleA、articleB,articleA有關鍵字keyword1、keyword2,articleB有關鍵字keyword3、keyword4。
我們現在想查詢含有關鍵字keyword1或者keyword3的所有文章列表,正確的結果應該是articleA和articleB兩條記錄。然而,如果使用hibernate不當,有可能你得到的是articleA、articleA、articleB、articleB四條記錄,其中兩條是重復的。
這是怎么發生的呢?
如果我們這樣使用hibernate來實現這個查詢:
看看hibernate給我們生成的sql語句:
articleA keyword1 keyword1
articleA keyword1 keyword2
aritcleB keyword3 keyword3
articleB keyword3 keyword4
正是我們之前所說得到的錯誤結果。
仔細分析這個sql,其實問題就出在hibernate生成sql的時候,對同一個表keywordtable查詢了兩次(在from中出現兩次),因此就有了組合的可能性,可以想見,如果再多幾個需要查詢的關鍵字,同一個記錄重復的次數會更多。
其實,要正確的破解這個問題,我們可以自己寫sql語句,使用hibernate同樣支持的原生sql查詢,不使用hibernate的hql查詢。
hibernate在給我們帶來很多便利性的同時,也給我們多多少少帶來了一些麻煩,而這些問題的定位成本可能也會很高。要使用好工具,就要知道工具的優缺點,尤其是缺點要有足夠的風險控制。
革命尚未成功,同志仍需努力!
有如下兩個對象:文章和關鍵字。它們之間的關系,很明顯,是一對多的關系,一個文章可以有很多的關鍵字。
假設有文章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();
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約束的有如下幾個組合: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')
articleA keyword1 keyword1
articleA keyword1 keyword2
aritcleB keyword3 keyword3
articleB keyword3 keyword4
正是我們之前所說得到的錯誤結果。
仔細分析這個sql,其實問題就出在hibernate生成sql的時候,對同一個表keywordtable查詢了兩次(在from中出現兩次),因此就有了組合的可能性,可以想見,如果再多幾個需要查詢的關鍵字,同一個記錄重復的次數會更多。
其實,要正確的破解這個問題,我們可以自己寫sql語句,使用hibernate同樣支持的原生sql查詢,不使用hibernate的hql查詢。
hibernate在給我們帶來很多便利性的同時,也給我們多多少少帶來了一些麻煩,而這些問題的定位成本可能也會很高。要使用好工具,就要知道工具的優缺點,尤其是缺點要有足夠的風險控制。
革命尚未成功,同志仍需努力!