由Criteria设置的懒孩子

时间:2014-05-31 07:29:07

标签: java hibernate-4.x

我有一个Parent类和一个带有当前设置的Child类

@Entity
public class Parent {
   @OneToMany(mappedBy = "parent")
   private Set<Child> children;

   @Column
   private int type;
}

@Entity
public class Child {
   @ManyToOne
   @JoinColumn(name = "parent_id")
   private Parent parent;
}

对于某些函数,我想根据其类型查询父项时,会自动检索子项并将其填充到集合中。

这是我到目前为止所尝试的

res = getSession().createCriteria(
   Parent.class, "parent"
).createAlias(
   "parent.children", "children"
).add(
   Restrictions.eq("parent.type", type)
).setFetchMode(
   "children", FetchMode.JOIN // FetchMode.SELECT
).list();

当我运行单元测试时,getter总是等于Null(我在数据库中有数据和关系)

Parent parent = new Parent();
parent.setType(ParentType.WEEK);
parentDao.save(parent);

Child child = new Child();
child.setParent(parent);
childDao.save(child);

List<Parent> res = parentDao.findByType(0, 10, ParentType.WEEK, true);

assertNotNull(res.get(0).getChildren());
assertEquals(1, res.get(0).getChildren().size());

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您正在创建父级,将使用空子级列表,并将其保留。因此,Parent实例存储在第一级缓存中。

然后你要创造一个孩子并坚持下去。

然后,您正在执行检索刚刚创建的父级的查询。因此,Hibernate从数据库中获取ID,发现该ID是已经在缓存中的Parent实体之一,因此返回该Parent实例。由于你还没有设置它的子列表,它仍然是空的。

您有责任保持实体图在内存中的一致性。 Hibernate只关心关联的拥有方。通过设置子项的父项,但不将子项添加到父项的子项中,您在实体图中引入了不连贯性。数据库中的一切都会很好,因为关联的拥有方是正确初始化的。

如果您启动新事务并执行查询,则会正确填充子列表。同样,如果在执行查询之前清除会话。但是在同一个事务中,Hibernate在初始化另一个时不会自动初始化关联的一面。