简体   繁体   English

Hibernate自引用关系和延迟加载

[英]Hibernate self-reference relationship and lazy loading

Before asking the question, here is the context of my problem: 在提出问题之前,这是我的问题的背景:

I got a specific entity named 'Category', which have a property Category (a parent) and another property of type 'relatedEntity'. 我有一个名为'Category'的特定实体,它有一个属性Category(父类)和另一个类型'relatedEntity'的属性。

Here is a sample of the code: 以下是代码示例:

@Entity
public class Category {

    ...

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

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

    ...
}

So, as you can see, I've declared ManyToOne relationships for these properties, and also a lazy loading fetching strategy. 因此,正如您所看到的,我已经为这些属性声明了ManyToOne关系,并且还为延迟加载提取策略。

Now, I use this method inside a DAO object to get a list of Category: 现在,我在DAO对象中使用此方法来获取Category列表:

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

I got a specific service object which calls the DAO method: 我有一个调用DAO方法的特定服务对象:

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

Nothing really extraordinary for the moment... Now, here come my unit tests: 暂时没什么特别的......现在,来我的单元测试:

@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) {}
    }
}

After running the test, an exception is catched in the first try/catch block and the second fail is fired, saying that there is no LazyInitException on the parent property of the category. 运行测试后,在第一个try / catch块中捕获异常,并触发第二个失败,表示类别的父属性上没有LazyInitException。

So I can call 所以我可以打电话

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

or 要么

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

without any exception being raised. 没有任何例外被提出。

I've set 'show_sql=true' in my configuration file, I can't see any supplementary request in my logs after calling the getter on the parent property, so there is no new request but the parent property is loaded. 我在配置文件中设置了'show_sql = true',在父属性上调用getter之后,我在日志中看不到任何补充请求,因此没有新请求但是父属性已加载。

Can somebody explain me why the parent property is not lazy? 有人可以解释一下为什么父母财产不懒惰吗?

EDIT: 编辑:

I've updated my test case. 我已经更新了我的测试用例。

@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());     
    }       
}

And now the test is passing... Was it related to the access of the entity property (via c.getEntity()) in my previous test case? 现在测试正在通过......它是否与我以前的测试用例中的实体属性(通过c.getEntity())的访问有关?

Could you try getting only one Category instead of loading them all ? 你能尝试只获得一个类别而不是全部加载吗?

Indeed, when you are loading a Category , if hibernate can find its parent in the same Session , it will initialize it, even if parent is marked as lazy. 实际上,当你加载一个Category时 ,如果hibernate可以在同一个Session中找到它的父级 ,它将初始化它,即使parent被标记为lazy。 As you are querying for all categories, it will find all the parents in the Session and initialize them. 当您查询所有类别时,它将在会话中找到所有父项并初始化它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM