hel*_*llo 2 java gwt hibernate jpa
我有双向关系设置如下:
class Child{
@ManyToOne
@JoinTable(name = "CHILDREN_WITH_PARENT",
joinColumns = {@JoinColumn(name = "CHILD_ID")},
inverseJoinColumns = {@JoinColumn(name = "PARENT_ID")}
)
private Parent parent;
}
class Parent{
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL)
Set<Child> childrens = new HashSet<Child>();
public void persistOrMerge() {
EntityManager em = entityManager();
em.getTransaction().begin();
try {
if (em.contains(this))
return;
if (id == null || id == 0) {
this.setCreatedDate(new Date());
em.persist(this);
} else {
Parent prev = em.find(Parent.class, this.id);
if (prev == null) {
em.persist(this);
} else{
this.setCreatedDate(new Date());
em.merge(this);
}
}
em.flush();
em.getTransaction().commit();
} finally {
em.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的客户端,我有以下代码(GWT + EntityProxy)
Set<ChildProxy> children = new HashSet<ChildProxy>();
if(childIsNew)
child = request.create(Children.class)
else
child = request.edit(oldChild)
children.add(child);
//If children are deleted, they are not contained in the set
//we are sending back to server
parent.setChildren(children)
parent.persistOrMerge();
Run Code Online (Sandbox Code Playgroud)
此代码仅适用于添加新子项.即使父类接收到空子集,从父项中删除子项也不起作用.JOIN表中的链接不会被删除.
你能告诉我哪里遗失了什么吗?
谢谢!
我首先要说的是,实体是直接使用实体管理器的实体是一个非常糟糕的主意.
EntityManager.merge()方法返回实际的合并实例,这意味着在您的代码中,当您发布时
em.merge(this)
Run Code Online (Sandbox Code Playgroud)
您不能保证合并的实例不再对应于"this",从那时起您可能会看到各种逻辑问题.
如果您认为这不是一件大事,那么您的问题应该通过在关系的OneToMany端启用孤儿删除来解决,前提是孩子不会在其他关系中的其他地方使用.否则,您将不得不手动进行合并.
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL, orphanRemoval=true)
Set<Child> childrens = new HashSet<Child>();
Run Code Online (Sandbox Code Playgroud)
JPA 2.0规范指出了这一点
指定为OneToOne或OneToMany的关联支持使用orphanRemoval选项.当orphanRemoval生效时,以下行为适用: