2012-03-14 6 views
2

私はユーザとメッセージテーブルを持っています。 User to Messageは1対多の関係であり、Message to Userは多対1の関係です。フェッチ・ジョインとして多対1のいずれかをマークしました。 1つのMessageを取得すると、Hibernateはjoinクエリを実行しますが、すべてのメッセージを取得すると、Hibernateはjoinの代わりにselectクエリを実行します。理由は何でしょうか?次の詳細は:それらの間奇妙な動作をフェッチするHibernate 'join'

関係:

ユーザー

<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は予想通り1は、クエリに参加し実行します。

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クエリに対して、マッピングで定義されたフェッチ戦略を必ずしも使用しないようです。通常、get/loadに使用されます。ここに参照が見つかりました:https://forum.hibernate.org/viewtopic.php?f=1&t=957561

+0

"通常はget/loadに使用されます。" <=修正:load()に*使用されます。また、N + 1 SELECTSの問題を別の方法で解決することもできます。レイジーセレクトを有効にし、エンティティのバッチサイズを有効にします。 –

0

私はわかりませんが、これが理由かもしれません。結合または副問合せである単一の問合せを実行する場合1つのクエリではパフォーマンスの違いはありません。しかし、複数のクエリを実行している場合(複数のメッセージの場合)、パフォーマンスの問題が発生する可能性があります。私は間違いなく結合/サブクエリの代わりに単純な選択クエリを選択します。パフォーマンスを考慮すると、これは間違いありません。これは、Hibernateの機能です。

+0

私はこれが私の質問に答えないと思います。私の質問は、2番目のクエリでHibernateが示す予期しない動作です。なぜそれはそのように振る舞うのですか? – shrini1000

+0

パフォーマンスのためです。パフォーマンスを向上させるために、hibernateはjoinの代わりにselectクエリを使用しているかもしれません。私はあなたの質問にすでに答えました。 –

+1

なぜ複数の選択クエリを実行する方が単一の結合クエリを実行するよりもパフォーマンスが良いと思いますか?実際、join fetchのポイントは 'n + 1 select'の問題を取り除くことです! – shrini1000