JPA 中的级联类型

Cascade types in JPA

给定两个实体 DepartmentEmployee 形成从 DepartmentEmployee 的一对多关系。

由于关系非常直观,我省略了实体 类。

Department中:

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

Employee中:

@ManyToOne(fetch = FetchType.LAZY)
private Department department;

请注意我没有提到cascade = {CascadeType.MERGE}虽然下面的关系在双方(拥有和反面)合并。

Employee employee = entityManager.find(Employee.class, 18L);
employee.setEmployeeName("zz");

Department department = employee.getDepartment();
employee.setDepartment(department);

department.setDepartmentName("e");
department.setLocation("e");

entityManager.merge(employee);

合并Employee的同时,Department也合并了

反之,在下面这个例子中,

Department department = entityManager.find(Department.class, 1L);
List<Employee> employeeList = department.getEmployeeList();

for(Employee e:employeeList) {
    if(e.getEmployeeId().equals(27L)) {
        e.setEmployeeName("xxx");
    }
}

// No further EntityManager operation(s) here.

设置为 Employee 实例的新值直接合并到关联的基础数据库中。

来自 OpenJPA :

CascadeType.MERGE: When merging entity state, also merge the entities held in this field.

来自 EclipseLink Wiki :

MERGE – If the owning entity is merged, the merge is cascaded to the target of the association.

来自 JPA Wiki Book

MERGE - Cascaded the EntityManager.merge() operation. If merge() is called on the parent, then the child will also be merged. This should normally be used for dependent relationships. Note that this only affects the cascading of the merge, the relationship reference itself will always be merged. This can be a major issue if you use transient variables to limit serialization, you may need to manually merge, or reset transient relationships in this case. Some JPA providers provide additional merge operations.

关于上面的测试用例,我不准确地理解什么时候需要或有用cascade = {CascadeType.MERGE}。在这种情况下 cascade = {CascadeType.MERGE} 有什么用?

那些测试用例如何在不使用 cascade = {CascadeType.MERGE} 的情况下分别合并 DepartmentEmployee

我目前使用的是 EclipseLink 2.6.0。

您缺少的是 JPA 的一个基本功能:对托管实体所做的每个更改都会自动保存到数据库中。无需调用 merge() 或其他任何东西。您打开一个事务,获取实体并修改它们,然后提交事务,这就是您需要修改数据库的全部内容。

merge() 用于将更改从 分离的 实体复制到其 托管的 对应实体。