【问题标题】:Hibernate self-reference relationship and lazy loadingHibernate自引用关系和延迟加载
【发布时间】:2012-11-14 10:07:57
【问题描述】:

在问这个问题之前,这里是我的问题的背景:

我有一个名为“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。

所以我可以打电话

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())有关?

【问题讨论】:

  • 您应该在单元测试中捕获异常并手动失败(或者在没有抛出异常时失败,如您的情况),您应该使用 @ 传播预期的异常987654328@.

标签: java hibernate unit-testing jpa lazy-loading


【解决方案1】:

您能否尝试只获取一个类别而不是全部加载?

确实,当你加载一个Category时,如果hibernate可以在同一个Session中找到它的parent,它会初始化它,甚至如果 parent 被标记为惰性。当您查询所有类别时,它将找到 Session 中的所有父级并初始化它们。

【讨论】:

  • 是的,似乎是一个很好的答案,我刚刚尝试了一个类别,并且在调用 getter parent 后捕获了 LazyInitException !在这种情况下不知道 Hibernate 的行为,谢谢!那里可能存在性能问题,因为我可以检索所有类别和链接的父母?
  • 好吧,我已经参考他的评论更新了我的测试用例并编辑了我的问题。我的测试更加原子并且只关注父属性,测试现在通过并且父级被延迟加载。但我不知道上次测试失败的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
相关资源
最近更新 更多