2012-03-14 41 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