java 为什么合并不在一对多关系上级联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13153237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why merging is not cascaded on a one to many relationship
提问by Mark Estrada
My question here is almost similar to my other question Explicit delete on JPA relationshipsbut I thought of simplifying it further to warrant more detailed answers.
我在这里的问题几乎类似于我的另一个问题Explicit delete on JPA 关系,但我想进一步简化它以保证更详细的答案。
Imagine I have a OneToMany relationship between a parent and a child.
想象一下,我在父母和孩子之间有一个一对多的关系。
@Entity
public class Parent {
private String name;
@OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private List<Child> children;
}
@Entity
public class Child {
private String name;
@ManyToOne
private Parent owner;
}
In my UI, I am showing a list of parent. User can choose one parent and he/she can edit the list of its children. To show this, I have used a currentParent variable to represent the current parent edited. User can choose to add/edit children's name.
在我的用户界面中,我显示了父级列表。用户可以选择一个父级,他/她可以编辑其子级列表。为了说明这一点,我使用了 currentParent 变量来表示当前编辑的父级。用户可以选择添加/编辑孩子的名字。
Upon clicking a button, I would save the new children's list using an EJB call.
单击按钮后,我将使用 EJB 调用保存新的子项列表。
@ViewScoped
public class MyBean(){
private Parent currentParent;
@EJB
private MyEJB myEJB;
public void saveChanges(){
myEJB.save(currentParent);
}
}
My EJB call looks like this.
我的 EJB 调用看起来像这样。
@Stateless
public class MyEJB{
@PersistenceContext(unitName = "MyPU")
private EntityManager em;
public void save(Parent parentNew){
Parent pOld = em.find(entityClass, p.getId());
if(pOld !=null){
pOld.setName(parentNew.getName());
pOld.setChildren(parentNew.getChildren());
em.merge(pOld);
}
}
}
My problem is that, I am able to change the name of the parent but any changes to the childrens list is not reflected into the DB. It does not alter or execute any SQL to delete/update/add childs.
我的问题是,我可以更改父项的名称,但对子项列表的任何更改都不会反映到数据库中。它不会更改或执行任何 SQL 来删除/更新/添加子项。
What could be the cause?
可能是什么原因?
UPDATE
更新
Well after some trial and error and reading thru various links, it seems that setting the orphanRemoval option in my @onetomany would solve my problem. Eclipselink automatically deletes the orphan rows during merging.
经过一些试验和错误并通过各种链接阅读后,似乎在我的@onetomany 中设置 orphanRemoval 选项可以解决我的问题。Eclipselink 会在合并期间自动删除孤立行。
So much for JPA complexity..
JPA 的复杂性就这么多了..
@Entity
public class Parent {
private String name;
@OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER,orphanRemoval = true)
private List<Child> children;
}
回答by Chris
This is a standard problem with merge. Changes to child objects in the collection will get picked up.
这是合并的标准问题。集合中子对象的更改将被获取。
The merge call can only cascade over objects that are in the list, so changes to objects not in the list get lost. Unfortunately, the oneToMany doesn't own the relationship: the child's ManyToOne does. So the child entities need to be merged for changes to be seen and pushed to the database. Child entities are independent objects and need to be merged individually when the are changed. That, or added to a different parent/tree to get merged.
合并调用只能级联列表中的对象,因此对不在列表中的对象的更改会丢失。不幸的是,oneToMany 不拥有这种关系:孩子的 ManyToOne 拥有。因此需要合并子实体以查看更改并将其推送到数据库。子实体是独立的对象,需要在更改时单独合并。那,或添加到不同的父/树以合并。
回答by Zaw Than oo
Your question What could be the cause?
. The cause is value content of parentNew
. If the parentNew
is one of the following cause, it will not effect/update to child.
你的问题What could be the cause?
。原因是 的值内容parentNew
。如果parentNew
是以下原因之一,它将不会影响/更新到孩子。
- No reference instance parent and child vise visa. ---> It will throw exception.
Parent
parameter value have null or empty list ofClild
--> This will be your cause.Child
don't get updated name from UI.--> This will be your cause.
- 无参考实例亲子签证。--->它会抛出异常。
Parent
参数值有 null 或空列表Clild
-->这将是您的原因。Child
不要从 UI 获取更新的名称。-->这将是您的原因。
Example. I quick write it. It is OK.
例子。我赶紧写。没关系。
Already exist data in DB
DB中已有数据
Parent Child
================== =======================================
'P001', 'Parent 1' 'C002', 'Child 2', 'P001'
'C003', 'Child 3', 'P001'
'C001', 'Child 1', 'P001'
After Upldated:
更新后:
Parent Child
================== =======================================
'P001', 'Update Parent 1' 'C002', 'Update Child 2', 'P001'
'C003', 'Update Child 3', 'P001'
'C001', 'Update Child 1', 'P001'
List<Child> clidList = new ArrayList<Child>();
Parent parent = new Parent("P001", "Update Parent 1", clidList);
Child c1 = new Child("C001", "Update Child 1", parent);
Child c2 = new Child("C002", "Update Child 2", parent);
Child c3 = new Child("C003", "Update Child 3", parent);
clidList.add(c1);
clidList.add(c2);
clidList.add(c3);
Parent existingParent = em.find(Parent.class, parent.getId());
existingParent.setName(parent.getName());
existingParent.setChildren(parent.getChildren());
em.merge(existingParent);