Configurando orphanRemoval como true ao migrar filhos de seus pais para outro pai

Notícia importante : Se você está lendo esta postagem, considere pesquisaresta postagem também para discussões aprofundadas.

É uma prática / situação / requisito bastante comum em que os filhos de um dos pais podem ser migrados para outro pai. O que acontece seorphanRemoval está configurado paratrue no lado inverso de tais relacionamentos?

Considere como exemplo, qualquer relacionamento simples de um para muitos, como a seguir.

Lado inverso (departamento):

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

Lado proprietário (empregado):

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

Ao mesclar uma operação / ação como a seguinte (em quedepartment é uma entidade independente fornecida por um cliente),

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);

Obviamente, a adição e remoção de um funcionário pode ser melhor realizada / manipulada usando métodos de gerenciamento de vínculo defensivo (relacionamento) nas entidades associadas.

Uma instância de departamento é fornecida por um cliente. É uma entidade desanexada. Pode ser o mesmo ou um departamento diferente, dependendo de uma ação administrativa executada pelo cliente em questão. Como resultado, se a instância do departamento fornecida por um cliente for diferente da instância mantida pelo atualEmployee, em seguida, ele deve ser removido primeiro da lista de funcionários (employeeList) mantido pelo atualvelho departamento no lado inverso associado a esseEmployee antes de adicioná-lo à lista de funcionários mantidos pelo novodepartment fornecido.

Como um palpite, oEmployee linha deve ser removida inadvertidamente do banco de dados enquanto remove oEmployee instância da lista de funcionários atualmente referenciados pelo departamento do funcionário - departamento antigo (antes que esta operação seja acionada), ou seja, ao migrar um filho de seu pai para outro pai, o filho precisa ser removido do pai nativo antes de ser adotado por outro pai e essa linha filho deve ser removida inadvertidamente do banco de dados (orphanRemoval = true)

A linha do funcionário na tabela do banco de dados, no entanto, permanece intacta com os valores atualizados da coluna. Nenhuma instrução DML, exceto umaUPDATE declaração são gerados.

Posso considerar que, migrar filhos de seus pais para outro pai dessa maneira, não os remove inadvertidamente da tabela do banco de dados como deverianão estar?

Atualmente usando o EclipseLink 2.6.0 com JPA 2.1.

EDITAR:

Se umEmployee A entidade é excluída apenas (portanto, não é adicionada à lista depois que foi excluída - não é migrada para outro pai, mas apenas excluída) da lista no lado inverso; sua linha correspondente é excluída do banco de dados também como de costume (orphanRemoval = true), mas a linha é simplesmente atualizada quando umEmployee A entidade (filho) é adicionada à lista de outro pai após ser excluída da lista de seu pai nativo (migração da entidade).

O provedor parece ser inteligente o suficiente para detectar a migração de filhos de seus pais para outro pai, como uma atualização.

O comportamento pode ser visto idêntico no Hibernate (4.3.6 final) e no EclipseLink (2.6.0), mas não pode ser invocado se for um comportamento específico do provedor (não portátil). Não consigo encontrar nada sobre esse comportamento na especificação JPA.

questionAnswers(1)

yourAnswerToTheQuestion