2012-03-14 66 views
2

我有一個用戶和一個消息表。用戶到消息是一對多的關係,消息到用戶是多對一的關係。我已將多對一中的一個標記爲提取連接。當我得到'單個消息時,Hibernate運行一個連接查詢,但是當我獲取所有消息時,Hibernate運行select查詢而不是連接。可能是什麼原因?以下是詳細內容:它們之間休眠'加入'獲取奇怪的行爲

關係:

用戶

<set name="messagesForFromUserUid" lazy="true" table="message" inverse="true" cascade="save-update"> 
     <key> 
      <column name="from_user_uid" not-null="true" /> 
     </key> 
     <one-to-many class="repository.Message" /> 
    </set> 
    <set name="messagesForToUserUid" lazy="true" table="message" fetch="select"> 
     <key> 
      <column name="to_user_uid" not-null="true" /> 
     </key> 
     <one-to-many class="repository.Message" /> 
    </set> 

消息

<many-to-one name="userByFromUserUid" class="repository.User" fetch="join" lazy="false"> 
     <column name="from_user_uid" not-null="true" /> 
    </many-to-one> 
    <many-to-one name="userByToUserUid" class="repository.User" fetch="select" lazy="proxy"> 
     <column name="to_user_uid" not-null="true" /> 
    </many-to-one> 

當我取一個單一的消息對象時,Hibernate會如期運行一個連接查詢:

Message m = (Message) s.get(Message.class, 2); 

Hibernate: 
select 
    message0_.message_uid as message1_1_1_, 
    message0_.from_user_uid as from2_1_1_, 
    message0_.to_user_uid as to3_1_1_, 
    message0_.message_text as message4_1_1_, 
    message0_.created_dt as created5_1_1_, 
    user1_.user_uid as user1_0_0_, 
    user1_.user_name as user2_0_0_, 
    user1_.user_password as user3_0_0_, 
    user1_.email as email0_0_, 
    user1_.first_name as first5_0_0_, 
    user1_.last_name as last6_0_0_, 
    user1_.created_dt as created7_0_0_ 
from 
    hello.message message0_ 
inner join 
    hello.user user1_ 
     on message0_.from_user_uid=user1_.user_uid 
where 
    message0_.message_uid=? 

但是,當我在一個拿來的全部信息,Hibernate的運行SELECT查詢來代替:

List<Message> l = s.createQuery("from Message").list(); 

Hibernate: 
select 
    message0_.message_uid as message1_1_, 
    message0_.from_user_uid as from2_1_, 
    message0_.to_user_uid as to3_1_, 
    message0_.message_text as message4_1_, 
    message0_.created_dt as created5_1_ 
from 
    hello.message message0_ 
Hibernate: 
select 
    user0_.user_uid as user1_0_0_, 
    user0_.user_name as user2_0_0_, 
    user0_.user_password as user3_0_0_, 
    user0_.email as email0_0_, 
    user0_.first_name as first5_0_0_, 
    user0_.last_name as last6_0_0_, 
    user0_.created_dt as created7_0_0_ 
from 
    hello.user user0_ 
where 
    user0_.user_uid=? 

Hibernate: 
select 
    user0_.user_uid as user1_0_0_, 
    user0_.user_name as user2_0_0_, 
    user0_.user_password as user3_0_0_, 
    user0_.email as email0_0_, 
    user0_.first_name as first5_0_0_, 
    user0_.last_name as last6_0_0_, 
    user0_.created_dt as created7_0_0_ 
from 
    hello.user user0_ 
where 
    user0_.user_uid=? 

回答

2

看起來好像Hibernate並不總是使用在映射中爲HQL或Criteria查詢定義的獲取策略。它們通常用於獲取/加載。在這裏找到一個參考:https://forum.hibernate.org/viewtopic.php?f=1&t=957561

+0

「它們通常用於獲取/加載。」 <=校正:它們被*用於*()。此外,您可以用不同的方式解決N + 1 SELECTS問題:啓用延遲選擇並在實體上啓用批處理大小。 – 2012-09-20 21:14:12

0

我不知道,但是這可能是原因。如果您運行單個查詢即聯接或子查詢。沒關係,單個查詢可能沒有任何性能差異。但是,如果您正在運行多個查詢(在您的情況下是多條消息),則可能會引發性能問題。我肯定會選擇簡單的select查詢,而不是join/subqueries。如果我們考慮性能,這絕對有意義。這就是Hibernate所做的。

+0

我不認爲這回答我的問題。我的問題是關於Hibernate在第二個查詢中顯示的意外行爲。它爲什麼這樣表現? – shrini1000 2012-03-14 08:39:41

+0

這是因爲性能。爲了提高性能,hibernate可能使用select查詢而不是join。我已經回答了你的問題。 – 2012-03-14 09:45:20

+1

爲什麼您認爲運行多個select查詢比運行單個連接查詢更有效?實際上,聯合提取的目的是消除'n + 1選擇'問題! – shrini1000 2012-03-14 09:50:16