当前位置: 首页 > 知识库问答 >
问题:

将孩子从父母迁移到另一个父母时,将orphanRemove设置为true

朱啸
2023-03-14

重要提示:如果你正在阅读这篇文章,那么也考虑看看这篇文章进行深入讨论。

这是一个非常常见的做法/情况/要求,其中一个父级的子级可以迁移到另一个父级。如果在这种关系的反面将孤儿删除设置为true会发生什么?

考虑作为示例,任何简单的一对多关系如下。

反面(部门) :

@OneToMany(mappedBy = "department", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Employee> employeeList = new ArrayList<Employee>(0);

拥有方(员工):

@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private Department department;

在合并如下操作/动作时(其中< code>department是由客户端提供的分离实体),

Employee employee = entityManager.find(Employee.class, 1L);
Department newDepartment = entityManager.contains(department) ? department : entityManager.merge(department);

if (!newDepartment.equals(employee.getDepartment())) {
    employee.getDepartment().getEmployeeList().remove(employee);
    // Since orphanRemoval is set to true, 
    // this should cause a row from the database table to be removed inadvertently
    // by issuing an addition DELETE DML statement.
}

employee.setDepartment(newDepartment);
employee.setEmployeeName("xyz");        

List<Employee> employeeList = newDepartment.getEmployeeList();

if (!employeeList.contains(employee)) {
    employeeList.add(employee);
}

entityManager.merge(employee);

当然,添加和删除员工可能最好使用关联实体中的防御性链接(关系)管理方法完成/处理。

部门实例由客户端提供。它是一个分离的实体。根据相关客户端执行的管理操作,它可以是相同的部门,也可以是不同的部门。因此,如果客户端提供的部门实例与当前员工持有的部门实例不同,则应首先将其从与该员工关联的反面上的当前旧部门持有的员工列表(员工列表)中删除,然后再将其添加到提供的新部门持有的员工列表中。

作为猜测,应无意中从数据库中删除 Employee 行,同时从员工部门 - 旧部门当前引用的员工列表中删除 Employee 实例(在触发此操作之前),即在将子项从其父级迁移到另一个父级时,需要从其本机父级中删除该子项,然后才能被另一个父级采用,并且该子行应该是无意中从数据库中删除(孤立删除 = true)。

但是,数据库表中的员工行与更新的列值保持不变。除了UPDATE语句之外,不生成任何DML语句。

我可以考虑一下,以这种方式将孩子从他们的父母迁移到另一个父母,不会无意中从数据库表中删除这些孩子吗?

目前使用的EclipseLink 2.6.0有JPA 2.1。

编辑:

如果一个员工实体仅从反向侧的列表中删除(因此,在它被删除后没有添加到列表中-没有迁移到另一个父级,而是刚刚删除),那么它的相应行也像往常一样从数据库中删除(孤儿删除=真),但当一个员工实体(子)在从其本机父级列表中删除后添加到另一个父级的列表中时,该行会被简单地更新(实体的迁移)。

提供者似乎足够聪明,能够检测到孩子从父母迁移到另一个父母的情况,作为一个更新。

在HiberNate(4.3.6最终版)和Eclipse Link(2.6.0版)上可以看到相同的行为,但如果它是特定于提供者的行为(不可移植),则不能依赖它。我在JPA规范中找不到有关此行为的任何内容。


共有1个答案

卜存
2023-03-14
匿名用户

这记录在JPA规范中。

第 3.2.4 节(摘录):

应用于实体X的刷新操作的语义如下:

  • 如果X是托管实体,则将其同步到数据库。
    • 对于来自X的关系引用的所有实体Y,如果与Y的关系已用级联元素值ca
    • =PERSIST或caade=ALL注释,则将持久化操作应用于Y

    第3.2.2节(节选):

    应用于实体X的持久化操作的语义如下:

    • 如果 X 是已删除的实体,则它将成为托管实体。

    孤立删除JPA javadoc:

    (可选)是否将删除操作应用于已从关系中删除的实体,并将删除操作级联到这些实体。

    < code>orphanRemovalHibernate文档:

    如果从@OneToOne集合中删除了一个实体,或者从@OneToOne关联中取消了关联实体的引用,则如果孤品移除设置为true,则可以将此关联实体标记为删除。

    因此,您从部门D1中删除员工E并将她添加到部门D2

    然后Hibernate将部门D1与数据库同步,发现E不在员工列表中,并将E标记为删除。然后,它将D2与数据库同步,并将PERSIST操作级联到员工列表中(第3.2.4节)。由于<code>E</code>现在在这个列表中,所以级联应用于它,Hibernate取消计划删除操作(第3.2.2节)。

    您可能也想看看这个问题。

    “如果在这种关系的反面将orphanRemove设置为true,会发生什么?”

    您已经在反面设置了它(反面是声明mapedBy的一面)。如果你的意思是如果它设置在另一边(在这种情况下是@ManyToOne),那么它就没有意义了,这就是为什么@ManyToOne@ManyToOne中没有这样的属性。

 类似资料:
  • 问题内容: 这是一种很常见的做法/情况/要求,其中父母的子女可以迁移到另一父母。如果设置为这种关系的反面会发生什么? 作为示例,考虑以下任何简单的一对多关系。 反面(系): 所属方(员工): 合并以下操作/动作(客户端提供的分离实体)时, 当然,使用关联实体中的防御性链接(关系)管理方法可以更好地完成/处理添加和删除员工的操作。 客户提供部门实例。它是一个独立的实体。它可以是相同的部门,也可以是不

  • 问题内容: 我在这里有一个简单的设置: 我有一个父组件,该父组件有2个子组件。在第一个子组件中:用户更改输入的值。然后,该更改的值将是我想要从该孩子传递给父对象的道具,以便可以将其传递给与同一父组件相连的另一个孩子。 当前设置的这个,请查看 从用户输入到UI更改的流程:1.在“ Child 1”中:调整一个滑块,将onChange值传递给父组件;2.将此属性(新的滑块值)传递给Parent组件,以

  • 问题内容: 在组件中,我需要将函数的返回值传递给属性。然后从属性需要被传递到的组件。新来的反应。不确定如何将属性从子级传递到组件。 问题答案: 您可以将函数从父级传递给子级,子级可以使用颜色调用该函数(很多操作都类似于事件处理程序)。在App中收到颜色后,使用.setState()将其分配给状态值,然后将其在render()中获取

  • 问题内容: 我有以下标记: 我希望将样式设置为“一个”和“三个”。 但是,标记也可以是: 我尝试使用以下CSS: 但是,正如预期的那样,这是每个样式的第一个子元素的样式。 如何更改CSS,以便可以定位属于的第1个和第3个? 问题答案: 您不能仅凭CSS选择器来做到这一点。和兄弟组合器仅限于共享其父代的子代/兄弟姐妹,正如其名称所暗示的那样,并且CSS选择器无法解释父子结构的这种变化,也没有类似选择

  • 实现一对多关系并选择父项和子项我有一个关系,我想进行查询(选择*) 文件夹。JAVA 作者。JAVA 我的请求: 我得到了这样的结果: 我的代码有什么问题?什么是问题,当我执行查询我得到了这个结果...我想得到这个结果

  • 我正在做一个物理模拟。 我有一个,它保存模拟中的所有对象。我有一个父类:,还有两个子类:和。 当然,父类没有方法,但每个子类都有。因此,当我在列表中循环绘制每个元素时,它不允许我这样做,因为类中没有方法(因为我将列表定义为