JPA CascadeType.ALL non elimina gli orfani


132

Ho problemi a eliminare i nodi orfani utilizzando JPA con il seguente mapping

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

Sto riscontrando il problema dei ruoli orfani in giro per il database.

Posso usare l'annotazione org.hibernate.annotations.Cascade tag specifico Hibernate ma ovviamente non voglio legare la mia soluzione in un'implementazione di Hibernate.

EDIT : sembra che JPA 2.0 includerà il supporto per questo.

Risposte:


164

Se lo stai usando con Hibernate, dovrai definire esplicitamente l'annotazione CascadeType.DELETE_ORPHAN, che può essere utilizzata insieme a JPACascadeType.ALL .

Se non prevedi di utilizzare Hibernate, dovrai prima eliminare esplicitamente gli elementi figlio e quindi eliminare il record principale per evitare qualsiasi record orfano.

sequenza di esecuzione

  1. recuperare la riga principale da eliminare
  2. recuperare elementi figlio
  3. elimina tutti gli elementi figlio
  4. elimina la riga principale
  5. sessione chiusa

Con JPA 2.0, ora puoi usare l'opzione orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)

3
grazie ho finito per seguire questa strada, penso che questo sia un po 'fuori sede per le specifiche JPA.
Paul Whelan,

13
Lo standard JPA 2.0 ora ha deleteOrphan come attributo a @OneToMany Se stai usando l'ultimo letargo puoi fare @OneToMany (..., deleteOrphan = true)
jomohke,

qual è la sequenza di esecuzione quando aggiorno solo elementi figlio? i record orfani saranno cancellati?
jAckOdE,

113

Se si utilizza JPA 2.0, è ora possibile utilizzare l' orphanRemoval=trueattributo di@xxxToMany dell'annotazione per rimuovere gli orfani.

In realtà, CascadeType.DELETE_ORPHANè stato deprecato in 3.5.2-Final.


6
In realtà penso che orphanRemoval = true significhi qualcos'altro, ovvero eliminare un oggetto quando lo rimuovo dalla sua raccolta padre. Vedi download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie

Per favore g tramite il link di Archie.
Jigar Shah,

4
orphanRemoval = true non funziona neanche. Deve essere fatto alla vecchia maniera.
Joe Almore,

45
╔═════════════╦═════════════════════╦═════════════════════╗
   Action      orphanRemoval=true    CascadeType.ALL   
╠═════════════╬═════════════════════╬═════════════════════╣
   delete         deletes parent      deletes parent   
   parent         and orphans         and orphans      
╠═════════════╬═════════════════════╬═════════════════════╣
   change                                              
  children      deletes orphans         nothing        
    list                                               
╚═════════════╩═════════════════════╩═════════════════════╝

1
Cosa succede se ho cascade = CascadeType.ALL, orphanRemoval = falseed elimino il genitore? Eliminerà i bambini, anche se ho specificamente detto di NON farlo?
izogfif


7

è possibile utilizzare @PrivateOwned per eliminare gli orfani, ad es

@OneToMany(mappedBy = "masterData", cascade = {
        CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;

5
Grazie a @reshma va notato che @PrivateOwned è un'estensione JPA eclipselink.
Paul Whelan,

5

Trovo solo questa soluzione ma nel mio caso non funziona:

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

orphanRemoval = true non ha alcun effetto.


1
Avevo bisogno di pulire e costruire prima che il cambiamento entrasse in vigore.
maralbjo,

Wow, ho cercato per un'ora perché aggiungere CascadeType.ALL sul mio ManyToOne non fosse eliminare a cascata. Pulito e costruito e funziona. Grazie @maralbjo.
Andrew Mairose,


2

Ho avuto lo stesso problema e mi chiedevo perché questa condizione di seguito non eliminasse gli orfani. L'elenco dei piatti non è stato eliminato in Hibernate (5.0.3.Final) quando ho eseguito una query di eliminazione denominata:

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

Poi mi sono ricordato che non dovevo usare una query di eliminazione denominata , ma EntityManager. Mentre utilizzavo il EntityManager.find(...)metodo per recuperare l'entità e quindi EntityManager.remove(...)per eliminarla, anche i piatti venivano eliminati.


2

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

Rimuovi targetEntity = MyClass.class , funziona benissimo.



0

Stavo usando il mapping uno a uno, ma il bambino non veniva cancellato L'APP stava violando la chiave esterna

Dopo aver utilizzato orphanRemoval = true, il problema è stato risolto


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") privato Bambino figlio;
Vipin Chauhan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.