我有一个关于 Hibernate 3.6.7 和 JPA 2.0 的问题。
考虑以下实体(为简洁起见,省略了一些 getter 和 setter):
@Entity
public class Parent {
@Id
@GeneratedValue
private int id;
@OneToMany(mappedBy="parent")
private List<Child> children = new LinkedList<Child>();
@Override
public boolean equals(Object obj) {
return id == ((Parent)obj).id;
}
@Override
public int hashCode() {
return id;
}
}
@Entity
public class Child {
@Id
@GeneratedValue
private int id;
@ManyToOne
private Parent parent;
public void setParent(Parent parent) {
this.parent = parent;
}
@Override
public boolean equals(Object obj) {
return id == ((Child)obj).id;
}
@Override
public int hashCode() {
return id;
}
}
现在考虑这段代码:
// persist parent entity in a transaction
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Parent parent = new Parent();
em.persist(parent);
int id = parent.getId();
em.getTransaction().commit();
em.close();
// relate and persist child entity in a new transaction
em = emf.createEntityManager();
em.getTransaction().begin();
parent = em.find(Parent.class, id);
// *: parent.getChildren().size();
Child child = new Child();
child.setParent(parent);
parent.getChildren().add(child);
em.persist(child);
System.out.println(parent.getChildren()); // -> [Child@1, Child@1]
em.getTransaction().commit();
em.close();
子实体被错误地插入父实体的子实体列表中两次。
执行以下操作之一时,代码可以正常工作(列表中没有重复的条目):
- 去除
mappedBy
父实体中的属性
- 对子列表执行一些读取操作(例如取消注释行标记
*
)
这显然是一种非常奇怪的行为。此外,当使用 EclipseLink 作为持久性提供程序时,代码将按预期工作(无重复)。
这是 Hibernate 错误还是我遗漏了什么?
Thanks
这是 Hibernate 中的一个错误。令人惊讶的是,目前还没有报道,请随时举报 https://hibernate.onjira.com/secure/Dashboard.jspa.
针对未初始化惰性集合的操作会排队,以便在集合初始化后执行它们,并且 Hibernate 不会处理这些操作与数据库中的数据冲突的情况。通常这不是问题,因为该队列在flush()
,并且可能的冲突更改将传播到数据库flush()
以及。然而,一些变化(例如持久化具有由类型生成器生成的 id 的实体)IDENTITY
,我想,这是你的情况)被传播到数据库,没有完整的flush()
,并且在这些情况下可能发生冲突。
作为解决方法,您可以flush()
坚持孩子后的会话:
em.persist(child);
em.flush();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)