Hibernate自引用关系和懒惰加载



在问这个问题之前,这里是我的问题的上下文:

我得到了一个名为"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对象中使用这个方法来获得Category:的列表

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块中捕获一个异常,并激发第二个fail,表示类别的父属性上没有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())有关?

你能试着只获取一个类别而不是全部加载吗?

事实上,当您加载类别时,如果hibernate能够在同一会话中找到其父级,则它将对其进行初始化,即使其父级话中找到所有父级并初始化它们。

最新更新