我有3种类型的对象 - Parent,Child和ChildAttr
我的目标是使用Hibernate(3.2.5)将子集的子集从一个Parent转移到另一个Parent。
对象的结构如下:
public class Parent {
Set<Child> children;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "parent")
@Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public Set<Child> getChildren() {
return this.children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
}
...
public class Child {
Set<ChildAttr> attributes;
Parent parent;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "child")
@Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public Set<ChildAttr> getAttributes() {
return this.attributes;
}
public void setAttributes(Set<ChildAttr> attributes) {
this.attributes = attributes;
}
}
...
public class ChildAttr {
Child child;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "child_id", nullable = false)
public Child getChild() {
return this.child;
}
public void setChild(Child child) {
this.child = child;
}
}
现在说我运行一些客户端代码,它接受Parent A的Child对象的子集并将它们移动到Parent B:
Set<Child> children = getChildrenToTransfer(transferCriteria, parentA);
parentA.getChildren().removeAll(children);
manager.saveOrUpdate(parentA); // method also calls flush();
parentB.getChildren().addAll(children);
manager.saveOrUpdate(parentB); // error thrown here.
尝试保存parentB时出现错误。
Found two representations of same collection: com.mycode.Child.attributes;
目前,应用程序似乎可以在多个会话中正常工作 - 例如 - 一些用户出现并删除了一组子项,然后一段时间后将它们添加到其他父项。此外,我真的不明白为什么它实例化该属性列表的多个版本时它应该真的只是一个,即使父更改。
导致上述错误的原因是什么?如何绕过它?
答案 0 :(得分:1)
因为您的双向关系(父子关系),这是因为。当您将子项移除/添加到另一个父项时,您应该更新parent
引用。
答案 1 :(得分:1)
一条经验法则:在尝试保持对象之前确保对象与对象图形一致... i您要从父A中删除所有子项并将它们添加到parentB但是您还没有更新这些孩子的父母链接。
所以我建议如下:
向Parent添加方法:
add(Child child) {
child.setParent0(this);
children.add(child);
}
remove(Child child) {
child.setParent0(null);
children.remove(child);
}
然后是孩子:
setParent0(Parent parent) {
this.parent = parent;
}
setParent(Parent parent) {
parent.add(this);
}
这样,当您从任一方向添加时,您都拥有一致的对象模型,而外部代码不知道详细信息。
从父母那里删除更有意义......
请尝试使用这些方法。