O JPA CascadeType.ALL não exclui órfãos

132

Estou tendo problemas para excluir nós órfãos usando JPA com o seguinte mapeamento

@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;

Estou tendo o problema das funções órfãs penduradas no banco de dados.

Posso usar a org.hibernate.annotations.Cascadetag específica Hibernate da anotação, mas obviamente não quero vincular minha solução a uma implementação Hibernate.

EDIT : Parece que o JPA 2.0 incluirá suporte para isso.

Paul Whelan
fonte

Respostas:

164

Se você o estiver usando com o Hibernate, terá que definir explicitamente a anotação CascadeType.DELETE_ORPHAN, que pode ser usada em conjunto com o JPA CascadeType.ALL.

Se você não planeja usar o Hibernate, terá que excluir explicitamente primeiro os elementos filhos e, em seguida, excluir o registro principal para evitar registros órfãos.

sequência de execução

  1. buscar a linha principal a ser excluída
  2. buscar elementos filho
  3. excluir todos os elementos filho
  4. excluir linha principal
  5. Fechar sessão

Com o JPA 2.0, agora você pode usar a opção orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)
Varun Mehta
fonte
3
graças, acabei indo por esse caminho, acho que isso é um pouco exagerado para as especificações da JPA.
Paul Whelan
13
O padrão JPA 2.0 tem agora deleteOrphan como um atributo para @OneToMany Se você está usando a última hibernação você pode fazer @OneToMany (..., deleteOrphan = true)
jomohke
o que é sequência de execução quando eu apenas atualizo elementos filho? os registros órfãos serão excluídos?
JAckOdE
113

Se você estiver usando o JPA 2.0, agora poderá usar o orphanRemoval=trueatributo da @xxxToManyanotação para remover órfãos.

Na verdade, CascadeType.DELETE_ORPHANfoi preterido na versão 3.5.2-Final.

Kango_V
fonte
6
Na verdade, acho que orphanRemoval = true significa outra coisa, ou seja, excluir um objeto quando removê-lo da coleção de seus pais. Veja download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie
Por favor, acesse o link do Archie.
Jigar Shah
4
orphanRemoval = true também não funciona. Isso tem que ser feito da maneira antiga.
precisa
45
╔═════════════╦═════════════════════╦═════════════════════╗
   Action      orphanRemoval=true    CascadeType.ALL   
╠═════════════╬═════════════════════╬═════════════════════╣
   delete         deletes parent      deletes parent   
   parent         and orphans         and orphans      
╠═════════════╬═════════════════════╬═════════════════════╣
   change                                              
  children      deletes orphans         nothing        
    list                                               
╚═════════════╩═════════════════════╩═════════════════════╝
Sergii Shevchyk
fonte
1
O que acontece se eu tiver cascade = CascadeType.ALL, orphanRemoval = falsee excluir os pais? Ele excluirá os filhos, mesmo que eu tenha dito especificamente para NÃO?
Izogfif 04/04
7

você pode usar o @PrivateOwned para excluir órfãos, por exemplo

@OneToMany(mappedBy = "masterData", cascade = {
        CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;
reshma
fonte
5
Obrigado @reshma, observe que @PrivateOwned é uma extensão JPA do eclipselink.
Paul Whelan
5

Acabei de encontrar esta solução, mas no meu caso, não funciona:

@OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) 

orphanRemoval = true não tem efeito.

Valéry Stroeder
fonte
1
Eu precisava limpar e construir antes da mudança entrar em vigor.
Maralbjo 15/05
Uau, estou procurando há uma hora por que adicionar CascadeType.ALL no meu ManyToOne não foi uma exclusão em cascata. Limpo e construído e funciona. Obrigado @maralbjo.
Andrew Mairose
4

De acordo com o Java Persistence with Hibernate , a exclusão órfã em cascata não está disponível como uma anotação JPA.

Também não é suportado no JPA XML.

kit de ferramentas
fonte
2

Eu tive o mesmo problema e me perguntei por que essa condição abaixo não excluiu os órfãos. A lista de pratos não foi excluída no Hibernate (5.0.3.Final) quando eu executei uma consulta de exclusão nomeada:

@OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Dish> dishes = new ArrayList<>();

Então lembrei que não devo usar uma consulta de exclusão nomeada , mas o EntityManager. Como usei o EntityManager.find(...)método para buscar a entidade e EntityManager.remove(...)excluí-la, os pratos também foram excluídos.

Bevor
fonte
2

Apenas @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true).

Remova targetEntity = MyClass.class , funciona muito bem.

Kohan95
fonte
1

Para os registros, no OpenJPA anterior ao JPA2, era @ElementDependant.

Simone Gianni
fonte
0

Eu estava usando o mapeamento individual, mas o filho não estava sendo excluído O JPA estava violando a chave estrangeira

Depois de usar orphanRemoval = true, o problema foi resolvido

vipin chauhan
fonte
@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (nome = "CHILD_OID") private Child child;
vipin chauhan