将子从其父迁移到另一个父时,将orphanRemoval设置为true
这是一种很常见的做法/情况/要求,其中父母的子女可以迁移到另一父母。如果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
供应商所拥有的员工列表中。
可以猜测,在Employee
从Employee
雇员部门-
旧部门当前所引用的雇员列表中删除实例时(在触发此操作之前),即在将孩子从其父项迁移到父项时,应无意中从数据库中删除该行。另一个父级,则需要先从其父级父级中删除该子级,然后再不经意地从数据库(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规范中对此进行了记录。
第 节(节选):
应用于实体X的刷新操作的语义如下:
- 如果X是受管实体,则将其同步到数据库。
- 对于由X的关系引用的所有实体Y,如果已使用级联元素值Cascade = PERSIST或Cascade =
ALL注释了与Y的关系,则对Y应用持久性操作
第 节(节选):
应用于实体X的persist操作的语义如下:
orphanRemoval
JPA
javadoc:
(可选)是否 应用于已从关系中删除的实体,以及是否将删除操作应用于这些实体。
orphanRemoval
hibernate文档:
如果一个实体从删除
@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
。
以上是 将子从其父迁移到另一个父时,将orphanRemoval设置为true 的全部内容, 来源链接: utcz.com/qa/403207.html