Why merging is not cascaded on a one to many relationship

Mar*_*ada 15 java jpa eclipselink ejb-3.1

My question here is almost similar to my other question Explicit delete on JPA relationships but I thought of simplifying it further to warrant more detailed answers.

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;
}
Run Code Online (Sandbox Code Playgroud)

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.

Upon clicking a button, I would save the new children's list using an EJB call.

@ViewScoped
public class MyBean(){
    private Parent currentParent;
    @EJB
    private MyEJB myEJB;

    public void saveChanges(){
        myEJB.save(currentParent);
    }
}
Run Code Online (Sandbox Code Playgroud)

My EJB call looks like this.

@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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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.

What could be the cause?

UPDATE

经过一些试验和错误以及通过各种链接阅读后,似乎在我的@onetomany中设置orphanRemoval选项可以解决我的问题.Eclipselink会在合并期间自动删除孤立行.

对于JPA的复杂性来说......

@Entity
public class Parent {
    private String name;
    @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER,orphanRemoval = true)
    private List<Child> children;
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 7

这是合并的标准问题.将收集对集合中子对象的更改.

合并调用只能对列表中的对象进行级联,因此对不在列表中的对象的更改会丢失.不幸的是,oneToMany并不拥有这种关系:孩子的ManyToOne.因此,需要合并子实体以使更改被显示并推送到数据库.子实体是独立的对象,需要在更改时单独合并.那,或者添加到不同的父/树来合并.


Zaw*_* oo 1

你的问题What could be the cause?。原因是 的价值内容parentNew。如果parentNew是以下原因之一,则不会影响/更新子级。

  1. 没有参考实例父母和孩子虎钳签证。--->它将抛出异常。
  2. Parent参数值有 null 或空列表Clild-->这将是你的原因。
  3. Child不要从 UI 获取更新的名称。-->这将是你的原因。

例子。我赶紧写一下。没关系。

DB中已存在数据

Parent                      Child
==================    =======================================
'P001', 'Parent 1'   'C002', 'Child 2', 'P001'
                     'C003', 'Child 3', 'P001'
                     'C001', 'Child 1', 'P001'
Run Code Online (Sandbox Code Playgroud)

更新后:

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);
Run Code Online (Sandbox Code Playgroud)