当前位置: 首页 > 面试题库 >

将子从其父迁移到另一个父时,将orphanRemoval设置为true

萧献
2023-03-14
问题内容

这是一种很常见的做法/情况/要求,其中父母的子女可以迁移到另一父母。如果orphanRemoval设置为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;

合并以下操作/动作(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,则应首先从employeeList当前
部门所拥有的雇员列表中与之相反的一方将其删除,然后Employee再添加将其添加到新department供应商所拥有的员工列表中。

可以猜测,在EmployeeEmployee雇员部门-
旧部门当前所引用的雇员列表中删除实例时(在触发此操作之前),即在将孩子从其父项迁移到父项时,应无意中从数据库中删除该行。另一个父级,则需要先从其父级父级中删除该子级,然后再不经意地从数据库(orphanRemoval= true)中删除该子行。

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

我是否可以考虑以这种方式将子代从其父代迁移到另一个父代,是否会无意间从数据库表中删除那些子代, 而不 应该 这样 做?

当前使用具有JPA 2.1的EclipseLink 2.6.0。

编辑:

如果Employee仅从相反侧的列表中删除一个实体(因此,在删除该实体后不将其添加到列表中-
不会迁移到另一个父级,而只是删除了),则该对象对应的行也照常从数据库中删除(orphanRemoval = true)但是,当Employee实体(子级)从其本机父级列表中删除后,该实体(子级)被添加到另一个父级列表中时,该行只是被更新(实体的迁移)。

提供者似乎很聪明,可以检测到孩子从其父母到另一父母的迁移,作为更新。

在Hibernate(最终版4.3.6)和EclipseLink(2.6.0)上都可以看到相同的行为,但是如果它是提供程序特定的行为(不是可移植的),则不能依靠该行为。我在JPA规范中找不到有关此行为的任何信息。


问题答案:

JPA规范中对此进行了记录。

3.2.4 节(节选):

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

  • 如果X是受管实体,则将其同步到数据库。
    • 对于由X的关系引用的所有实体Y,如果已使用级联元素值Cascade = PERSIST或Cascade =
      ALL注释了与Y的关系,则对Y应用持久性操作

3.2.2 节(节选):

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

  • 如果X是已删除的实体,则它将被管理。

orphanRemovalJPA
javadoc:

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

orphanRemovalhibernate文档:

如果一个实体从删除@OneToMany集合或相关实体是由非关联@OneToOne的关联,这种关联的实体可以 标记为删除
,如果orphanRemoval设置为true

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

然后,Hibernate将部门D1与数据库同步,发现该部门E不在员工列表中,并标记E为删除。然后,它D2与数据库同步,并将PERSIST操作级联到员工列表(第3.2.4节)。由于E现在位于此列表中,因此级联将应用于此列表,并且Hibernate取消安排删除操作的时间表(第3.2.2节)。

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

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

您已经将它设置在反面(反面是声明的那一面mappedBy)。如果你的意思是,如果它被设置在什么 其他
方面(@ManyToOne在这种情况下),那就不是为什么没有在这样的属性意义和的@ManyToOne@ManyToMany



 类似资料:
  • 重要提示:如果你正在阅读这篇文章,那么也考虑看看这篇文章进行深入讨论。 这是一个非常常见的做法/情况/要求,其中一个父级的子级可以迁移到另一个父级。如果在这种关系的反面将设置为会发生什么? 考虑作为示例,任何简单的一对多关系如下。 反面(部门) : 拥有方(员工): 在合并如下操作/动作时(其中< code>department是由客户端提供的分离实体), 当然,添加和删除员工可能最好使用关联实体

  • VSCode很棒,但它需要稍微小心的设置。 有许多秘密提示要遵循,例如 vscode增加的另一个惊人的新特性: https://code.visualstudio.com/docs/editor/settings-sync

  • 如何将数据从一个活动转移到另一个活动并将其设置为文本视图? 这就是我的意图: 我想将questions_score传递到另一个活动,并将其设置为文本视图。

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

  • 我一直在设计一个基于Swing的桌面RPG程序,以促进带有GUI控制元素的基于文本的角色扮演。 为了促进这一点,每个正在运行的客户端都会获得一个带有所有重要JFrames的主桌面(托管客户端上的“GM Desktop”和远程客户端上的“Player Desktop”)。此外,GM和Players都可以为角色打开“透视桌面”,为他们提供一个单独的JDesktopPane,其中包含提供该角色视角的“角

  • 在我们公司,我们有一个必须使用的Eclipse错误/警告设置的严格列表。使用此列表编译更改时,在签入之前不应存在任何错误/警告。 这些错误/警告可以在Eclipse的首选项下找到- 我是IntelliJ用户。IntelliJ有一个类似的概念,叫做“检查”。检查设置可以在设置下找到- 是否有人知道如何将Eclipse错误/警告迁移到最接近的IntelliJ检查设置上。我可以看到有一种方法可以导出/导