【发布时间】:2011-12-15 18:29:48
【问题描述】:
我有一个关于 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 错误还是我遗漏了什么?
谢谢
【问题讨论】:
-
能否添加 setParent 方法和 equals/hashCode 方法的代码?
-
我刚刚添加了您要求的方法。但是,我认为这个问题与 equals / hashCode 无关。
-
您的 equals 方法不遵守 Object.equals 的约定。此外,当 ID 生成并分配给实体时,hashCode 会发生变化。如果删除 hashCode 和 equals 后错误消失,我不会感到惊讶。顺便提一句。 Hibernate 建议不要使用 ID 来实现 equals 和 hashCode。
-
感谢您的评论。我不知道在 equals 和 hashCode 中使用持久 id 的争议。但即使我删除了我的 equals 和 hashCode 实现,问题仍然存在。
标签: hibernate jpa-2.0 one-to-many