为什么合并不是在一对多关系上级联的

2022-09-03 02:48:46

我在这里的问题几乎与我关于JPA关系的显式删除的另一个问题相似,但我想进一步简化它,以确保更详细的答案。

想象一下,我在父母和孩子之间有一个一对多的关系。

@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;
}

在我的 UI 中,我显示父级列表。用户可以选择一个父项,他/她可以编辑其子项的列表。为了说明这一点,我使用了一个 currentParent 变量来表示当前编辑的父级。用户可以选择添加/编辑孩子的名字。

单击按钮后,我将使用 EJB 调用保存新的儿童列表。

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

    public void saveChanges(){
        myEJB.save(currentParent);
    }
}

我的 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);
        }
    }
}

我的问题是,我能够更改父级的名称,但对子级列表的任何更改都不会反映在数据库中。它不会更改或执行任何 SQL 来删除/更新/添加子级。

可能的原因是什么?

更新

经过一些试验和错误以及通过各种链接阅读,似乎在我的@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;
}

答案 1

这是合并的标准问题。对集合中子对象的更改将被拾取。

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


答案 2

您的问题 .原因是 的价值含量。如果 是以下原因之一,则不会影响/更新到子级。What could be the cause?parentNewparentNew

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

例。我快速写它。还行。

数据库中已存在数据

Parent                      Child
==================    =======================================
'P001', 'Parent 1'   'C002', 'Child 2', 'P001'
                     'C003', 'Child 3', 'P001'
                     'C001', 'Child 1', 'P001'

上调后:

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);

推荐