0

質問をする前に、ここに私の問題の文脈があります:

'Category'という名前の特定のエンティティを取得しました。このエンティティには、プロパティCategory(親)とタイプ'relatedEntity'の別のプロパティがあります。

コードのサンプルは次のとおりです。

@Entity
public class Category {

    ...

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="entityID")
    private RelatedEntity entity;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="parentID")
    private Category parent;

    ...
}

ご覧のとおり、これらのプロパティのManyToOneリレーションシップと、遅延読み込みフェッチ戦略を宣言しました。

ここで、DAOオブジェクト内でこのメソッドを使用して、カテゴリのリストを取得します。

public List<Category> getAll() {
    Criteria crit = sessionFactory.getCurrentSession().createCriteria(Category.class);
    return (crit.list());
}

DAOメソッドを呼び出す特定のサービスオブジェクトを取得しました。

@Transactional(readOnly = true)
public List<Category> getAllCategories() {
    return (categoryDAO.getAll());
}

今のところ本当に特別なことは何もありません...さて、ここに私のユニットテストがあります:

@Test
public void testCategories() {

    List<Category> cat = service.getAllCategories();
    assertNotNull(cat);
    assertFalse(cat.isEmpty());

    for (Category c : cat) {

        try {
            assertNotNull(c.getEntity().getName());
            fail("Expected lazy init. on Category.Entity");
        }
        catch(LazyInitializationException ex) {
             //Exception is caught
        }

        try {
            assertNotNull(c.getParent().getName());
            //No exception
            fail("Expected lazy init. on Category.Parent");
        }
        catch(LazyInitializationException ex) {}
    }
}

テストの実行後、最初のtry / catchブロックで例外がキャッチされ、カテゴリの親プロパティにLazyInitExceptionがないことを示す、2番目の失敗が発生します。

だから私は呼び出すことができます

c.getParent().getParent().getName(); 

また

c.getParent().getParent().getParent().getName() 

例外なく発生します。

構成ファイルで「show_sql=true」を設定しました。親プロパティでgetterを呼び出した後、ログに補足リクエストが表示されないため、新しいリクエストはありませんが、親プロパティが読み込まれます。

親プロパティが怠惰ではない理由を誰かが私に説明できますか?

編集:

テストケースを更新しました。

@Test(expected=LazyInitializationException.class)   
public void lazyCategoriesParentsList() {
    List<Category> cat = service.getAllCategories();

    assertNotNull(cat);
    assertFalse(cat.isEmpty());

    for (Category c : cat) {            
        assertNotNull(c.getParent().getName());     
    }       
}

そして今、テストは合格しています...以前のテストケースでは、エンティティプロパティへのアクセス(c.getEntity()を介して)に関連していましたか?

4

1 に答える 1

3

すべてをロードするのではなく、 1つのカテゴリだけを取得してみてください。

実際、カテゴリをロードしているときに、hibernateが同じセッションでそのを見つけることができれば、がレイジーとしてマークされていても、カテゴリを初期化します。すべてのカテゴリをクエリしているときに、セッション内のすべての親が検索され、それらが初期化されます。

于 2012-11-14T10:30:26.963 に答える