2017-09-08 16 views
0

Hibernateは怠惰な空のフェッチ

私はPostgresデータベースに接続されていると私は次のような問題に遭遇しましコンソールアプリケーション書いています、こんにちはまあ:

public List<String> getCommonInterestsOfMyFriends(long personId) { 

    Person personOfIntrest = session.get(Person.class, personId); 
    //fetch friends from db via get Call 
    int size = personOfIntrest.getFriends().size(); 
    int size2 = personOfIntrest.getFriendsWith().size(); 
    int size3 = personOfIntrest.getIntrests().size(); 

    Set<Tag> interests = personOfIntrest.getIntrests(); 

    Set<Person> allFriends = personOfIntrest.getFriendships().keySet(); 

    for (Person p : allFriends) { 

     Set<Tag> friendsInterests = p.getIntrests(); 
     friendsInterests.retainAll(interests); 
    } 
} 

Aをpersonは、Joinテーブルを使用してManyToMany関係によってモデル化された関心を持つことができます。 私は上記のコードを何回か呼びますが、関心のない人が出現するまではまったく問題ありません。 その後、すべてのPersonに対して、 "Interest"セットは空になります。私はまだ

// fetch associated data via fetch join 
    Query q = session.createQuery("SELECT p FROM Person p " 
           + "LEFT JOIN FETCH p.friends " 
           + "LEFT JOIN FETCH p.friendsWith " 
           + "LEFT JOIN FETCH p.intrests " 
           + "WHERE p.id = :id"); 
    q.setParameter("id", personId); 
    Person personOfIntrest = (Person) q.getSingleResult(); 

同じ問題に合流フェッチ私も試してみました、ゲッター呼び出す怠惰な関連をintializeする

。 興味のない人の質問をしない限り、興味のあるセットが正常に読み込まれます。その後、その人のセットは空です。 これはすべて同じセッション内にあります。ヘルプ

おかげで、 種類は、将来的には思って誰のために

+0

それはその人の、あなたが話しているこのコードでinvoved多くの人のどの知らなくても、何が起こるかを理解するのは難しいですしかし、コードはretainAll()を多くの人の興味のため呼び出すので、セットからの関心が取り除かれます。特に1人の人に興味がない場合 –

+0

はい、問題は9行目のgetIntrests()の最初の呼び出しです。 例を教えてください。 I qu ID 9のPersonの場合、このPersonにはjoinテーブルに関連する列があり、intrestsがロードされていれば、すべて正常です。 次に、intrestsを持たないID 10のPersonを照会します。そのため、セットは空でもあります。 同じセッションで、私が人9を再度照会すると、intrestsのセットは空になります。その後、実際にintrestsを持っているかどうかにかかわらず、すべての人が同じです。 これは交差部分の前にあります。なぜこの部分が混乱しているのかわかります。おそらくその部分を削除する必要があります。 – IVIerlski

+0

削除した部分がおそらく問題の原因です。この方法は、複数の人に共通の関心を戻すことになっていますが、見つかった人のすべての友人の利益を変更します。なぜあなたはそれらのセットを変更するのですか?それがHibernateのバグだとは思わないでください。それはあなたのコードのバグです。 –

答えて

0

について:

私はセットにfriendsInterests.retainAll(interests);を呼び出すことで、友人の利益を操作することになりました。この変更は永続化されていないので、大きな問題ではないと私は思った。

同じセッションであっても、永続オブジェクトgetterまたはクエリを再度呼び出すとデータベースからオブジェクトをリロードすると誤って考えました。これはそうではありません!

私は深いコール前に設定をコピーして、すべてが期待どおりに動作します知っている:

for (Person p : allFriends) { 

     Set<Tag> friendsInterests = p.getIntrests(); 
     Set<Tag> fiCopy = new HashSet<Tag>(); 
     fiCopy.addAll(friendsInterests); 

     fiCopy.retainAll(interests); 
} 
関連する問題