Is it necessary to remove an entity from the colle

2019-09-01 13:33发布

问题:

Inverse side (Department) :

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

Owning side (Employee) :

@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY)
private Department department;

The method that merges an Employee entity supplied by a client having a null Department in it :

public Employee update(Employee employee) {
    Department department = employee.getDepartment();

    if (department == null) {
        Employee managedEmployee = entityManager.find(Employee.class, employee.getEmployeeId());
        // Obtain the original Employee entity which may still have its Department intact.

        if (managedEmployee == null) {
            throw new EntityNotFoundException();
        }

        Department managedDepartment = managedEmployee.getDepartment();

        if (managedDepartment != null) {
            managedEmployee.getDepartment().getEmployeeList().remove(managedEmployee);
            // Removing an Employee entity from the list on the inverse side,
            // since it will no longer be pointing to Employee after Employee is merged.
        }

        return entityManager.merge(employee);
    }
}

The supplied Employee is a detached entity. Suppose that Department is optional for Employees and hence, there is a null foreign key (ON DELETE SET NULL).

Is it necessary to explicitly remove an Employee entity as shown in the update() method above from the employee list on the inverse side of the relationship (Department), when the supplied Employee does not contain a Department (because it has already been set to null by the client while editing the Employee entity) before merging the supplied Employee entity?

I think, the provider will keep, the Employee reference in the list of employees on the inverse side of the relationship, on dangling otherwise.

It is generally impractical to have an employee without a department but this is just an example. Needless to mention that null foreign keys exist in other types of associations.

回答1:

My reading of Chapter 2.9 Entity Relationships of the JPA 2.1 Specification is that it is not necessary since you have specified orphanRemoval. Here are the words of the spec:

Associations that are specified as OneToOne or OneToMany support use of the orphanRemoval option. The following behaviors apply when orphanRemoval is in effect:

  • If an entity that is the target of the relationship is removed from the relationship (by setting the relationship to null or removing the entity from the relationship collection), the remove operation will be applied to the entity being orphaned. The remove operation is applied at the time of the flush operation. The orphanRemoval functionality is intended for entities that are privately "owned" by their parent entity. Portable applications must otherwise not depend upon a specific order of removal, and must not reassign an entity that has been orphaned to another relationship or otherwise attempt to persist it. If the entity being orphaned is a detached, new, or removed entity, the semantics of orphanRemoval do not apply.

  • If the remove operation is applied to a managed source entity, the remove operation will be cascaded to the relationship target in accordance with the rules of section 3.2.3, (and hence it is not necessary to specify cascade=REMOVE for the relationship).