【问题标题】:Get lazy children set by Criteria获取由 Criteria 设置的懒惰的孩子
【发布时间】:2014-05-31 07:29:06
【问题描述】:

我有一个具有当前设置的父类和一个子类

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

我该如何解决这个问题?

【问题讨论】:

  • 什么等于null?我假设返回 Set&lt;Children&gt; 的 getChildren() 怎么可能等于 1?
  • 哎呀,今天的咖啡不够喝!!!我编辑了我的问题。感谢@JBNizet
  • 上述代码应该可以正常工作,除非您正在加载的父级是您刚刚在同一个事务中创建的父级,并且您忽略了将其子列表初始化为其他内容无效的。 Hibernate 永远不会将集合初始化为 null。你也不应该这样做。
  • unless the parent you're loading is a parent that you've just created, in the same transaction, 正是它。我在同一个单元测试中创建了父项和子项,然后找到它(请查看完整的测试用例 - 刚刚编辑过)。如果我删除保存部分并使用旧数据库,那么它可以工作。非常感谢。如果你喜欢@JBNizet,你可以把你的评论变成答案

标签: java hibernate-4.x


【解决方案1】:

您正在创建一个父级,将一个空子级列表,并将其持久化。 Parent实例因此存储在一级缓存中。

然后你正在创建一个孩子并坚持它。

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

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

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

【讨论】:

  • +1 表示一级缓存。它解释了一切
猜你喜欢
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 2015-10-25
  • 2018-08-15
  • 2021-03-31
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多