Estou um pouco confuso sobre o orphanRemoval
atributo JPA 2.0 .
Acho que percebo que é necessário quando uso as ferramentas de geração de banco de dados do meu provedor de JPA para criar o DDL do banco de dados subjacente para ter uma ON DELETE CASCADE
relação específica.
No entanto, se o banco de dados existe e já possui uma ON DELETE CASCADE
relação, isso não é suficiente para fazer a exclusão da exclusão em cascata? O que o orphanRemoval
faz além disso?
Felicidades
fonte
Um exemplo tomado aqui :
Quando um
Employee
objeto de entidade é removido, a operação de remoção é conectada em cascata aoAddress
objeto de entidade referenciado . A este respeito,orphanRemoval=true
ecascade=CascadeType.REMOVE
são idênticos, e seorphanRemoval=true
for especificado,CascadeType.REMOVE
é redundante.A diferença entre as duas configurações está na resposta à desconexão de um relacionamento. Por exemplo, como ao definir o campo de endereço para
null
ou para outroAddress
objeto.Se
orphanRemoval=true
for especificado, aAddress
instância desconectada será removida automaticamente. Isso é útil para limpar objetos dependentes (por exemploAddress
) que não deveriam existir sem uma referência de um objeto proprietário (por exemploEmployee
).Se apenas
cascade=CascadeType.REMOVE
for especificado, nenhuma ação automática será executada, pois desconectar um relacionamento não é uma operação de remoção.Para evitar referências pendentes como resultado da remoção órfã, esse recurso deve ser ativado apenas para campos que contêm objetos dependentes particulares não compartilhados.
Espero que isso torne mais claro.
fonte
No momento em que você remover uma entidade filha da coleção, você também removerá essa entidade filha do banco de dados. orphanRemoval também implica que você não pode mudar de pai; se houver um departamento que tenha funcionários, depois de removê-lo para colocá-lo em outro departamento, você inadvertidamente removerá esse funcionário do banco de dados em liberação / confirmação (o que ocorrer primeiro). O moral é definir orphanRemoval como true, desde que você tenha certeza de que os filhos desse pai não migrarão para um pai diferente durante toda a sua existência. A ativação do orphanRemoval também adiciona REMOVE automaticamente à lista em cascata.
fonte
department.remove(emp);
que o empregado será excluída da tabela emp, mesmo sem chamarcommit()
O mapeamento JPA equivalente para o DDL
ON DELETE CASCADE
écascade=CascadeType.REMOVE
. Remoção órfã significa que as entidades dependentes são removidas quando o relacionamento com a entidade "pai" é destruído. Por exemplo, se um filho for removido de um@OneToMany
relacionamento sem removê-lo explicitamente no gerenciador de entidades.fonte
cascade=CascadeType.REMOVE
NÃO é equivalente aON DELETE CASCADE
. Ao remover no código do aplicativo e não afeta no DDL, outro executado no DB. Veja stackoverflow.com/a/19696859/548473A diferença é:
- orphanRemoval = true: a entidade "Filho" é removida quando não é mais referenciada (seu pai não pode ser removido).
- CascadeType.REMOVE: A entidade "Filho" é removida apenas quando o "Pai" é removido.
fonte
Transições de estado da entidade
O JPA converte transições de estado da entidade para instruções SQL, como INSERT, UPDATE ou DELETE.
Quando você é
persist
uma entidade, está agendando a instrução INSERT para ser executada quandoEntityManager
for liberada, automática ou manualmente.quando você é
remove
uma entidade, está agendando a instrução DELETE, que será executada quando o contexto de persistência for liberado.Transições de estado da entidade em cascata
Por conveniência, o JPA permite propagar transições de estado de entidade de entidades pai para filho filho.
Portanto, se você tem uma
Post
entidade pai que tem uma@OneToMany
associação com aPostComment
entidade filho:A
comments
coleção naPost
entidade é mapeada da seguinte maneira:CascadeType.ALL
O
cascade
atributo informa ao provedor JPA para passar a transição do estado da entidade da entidade paiPost
para todas asPostComment
entidades contidas nacomments
coleção.Portanto, se você remover a
Post
entidade:O provedor JPA removerá a
PostComment
entidade primeiro e, quando todas as entidades filhas forem excluídas, aPost
entidade também será excluída :Remoção de órfãos
Quando você define o
orphanRemoval
atributo comotrue
, o provedor JPA agendará umaremove
operação quando a entidade filha for removida da coleção.Então, no nosso caso,
O provedor JPA removerá o
post_comment
registro associado, pois aPostComment
entidade não é mais referenciada nacomments
coleção:EM EXCLUIR CASCADE
O
ON DELETE CASCADE
é definido no nível FK:Depois de fazer isso, se você excluir uma
post
linha:Todas as
post_comment
entidades associadas são removidas automaticamente pelo mecanismo de banco de dados. No entanto, isso pode ser uma operação muito perigosa se você excluir uma entidade raiz por engano.Conclusão
A vantagem do JPA
cascade
e dasorphanRemoval
opções é que você também pode se beneficiar do bloqueio otimista para evitar atualizações perdidas .Se você usar o mecanismo de cascata JPA, não precisará usar o nível DDL
ON DELETE CASCADE
, o que pode ser uma operação muito perigosa se você remover uma entidade raiz que possui muitas entidades filhas em vários níveis.Para mais detalhes sobre este tópico, consulte este artigo .
fonte
CascadeType
. É um mecanismo complementar. Agora, você está confundindo remoção com persistência. A remoção de órfão é sobre a exclusão de associações não referenciadas, enquanto a persistência é sobre como salvar novas entidades. Você precisa seguir os links fornecidos na resposta para entender melhor esses conceitos.Resposta @ GaryK é absolutamente ótimo, eu passei uma hora procurando uma explicação
orphanRemoval = true
vsCascadeType.REMOVE
e isso me ajudou a entender.Resumindo:
orphanRemoval = true
funciona idêntico comoCascadeType.REMOVE
SOMENTE SE estamos excluindo object (entityManager.delete(object)
) e queremos que os objetos childs sejam removidos também.Em situações completamente diferentes, quando buscamos alguns dados como
List<Child> childs = object.getChilds()
e removemos um child (entityManager.remove(childs.get(0)
) usandoorphanRemoval=true
, a entidade correspondentechilds.get(0)
será excluída do banco de dados.fonte
A remoção de órfãos tem o mesmo efeito que ON DELETE CASCADE no seguinte cenário: - Digamos que tenhamos um relacionamento simples de muitos para um entre a entidade estudantil e uma entidade guia, em que muitos alunos podem ser mapeados para o mesmo guia e, no banco de dados, temos um relação de chave estrangeira entre a tabela Student e Guide, de forma que a tabela student tenha id_guide como FK.
// A entidade pai
Nesse cenário, o relacionamento é tal que a entidade estudantil é o proprietário do relacionamento e, como tal, precisamos salvar a entidade estudantil para manter o gráfico inteiro do objeto, por exemplo
Aqui estamos mapeando o mesmo guia com dois objetos de alunos diferentes e, como o CASCADE.PERSIST é usado, o gráfico de objetos será salvo como abaixo na tabela do banco de dados (MySql no meu caso)
Tabela do ALUNO: -
ID Nome Departamento Id_Guide
1 Roy ECE 1
2 Nick ECE 1
Tabela GUIA: -
ID NAME Salário
1 João $ 1500
e agora, se eu quiser remover um dos alunos, usando
e quando um registro de aluno é removido, o registro de guia correspondente também deve ser removido, é aí que o atributo CASCADE.REMOVE na entidade Student entra em cena e o que faz é: remove o aluno com o identificador 1, bem como o objeto de guia correspondente (identificador 1) Mas neste exemplo, há mais um objeto de aluno que é mapeado para o mesmo registro de guia e, a menos que usemos o atributo orphanRemoval = true na Entidade de guia, o código de remoção acima não funcionará.
fonte