JPA CascadeType.ALL ne supprime pas les orphelins


132

Je rencontre des difficultés pour supprimer des nœuds orphelins à l'aide de JPA avec le mappage suivant

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

J'ai le problème des rôles orphelins qui traînent dans la base de données.

Je peux utiliser la org.hibernate.annotations.Cascadebalise d' annotation spécifique à Hibernate mais je ne veux évidemment pas lier ma solution à une implémentation Hibernate.

EDIT : Il semble que JPA 2.0 inclura un support pour cela.

Réponses:


164

Si vous l'utilisez avec Hibernate, vous devrez définir explicitement l'annotation CascadeType.DELETE_ORPHAN, qui peut être utilisée conjointement avec JPA CascadeType.ALL.

Si vous ne prévoyez pas d'utiliser Hibernate, vous devrez d'abord supprimer explicitement les éléments enfants, puis supprimer l'enregistrement principal pour éviter tout enregistrement orphelin.

séquence d'exécution

  1. récupérer la ligne principale à supprimer
  2. récupérer les éléments enfants
  3. supprimer tous les éléments enfants
  4. supprimer la ligne principale
  5. Fermer la session

Avec JPA 2.0, vous pouvez désormais utiliser l'option orphanRemoval = true

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

3
merci j'ai fini par emprunter cette voie, je pense que c'est un peu un sur-site pour la spécification JPA.
Paul Whelan

13
La norme JPA 2.0 a maintenant deleteOrphan comme attribut à @OneToMany Si vous utilisez la dernière mise en veille prolongée, vous pouvez faire @OneToMany (..., deleteOrphan = true)
jomohke

Quelle est la séquence d'exécution lorsque je mets à jour simplement des éléments enfants? les enregistrements orphelins seront-ils supprimés?
jAckOdE

113

Si vous utilisez JPA 2.0, vous pouvez désormais utiliser l' orphanRemoval=trueattribut de l' @xxxToManyannotation pour supprimer les orphelins.

En fait, CascadeType.DELETE_ORPHANa été obsolète dans 3.5.2-Final.


6
En fait, je pense que orphanRemoval = true signifie autre chose, c'est-à-dire supprimer un objet lorsque je le supprime de la collection de ses parents. Voir download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie

Veuillez passer par le lien d'Archie.
Jigar Shah du

4
orphanRemoval = true ne fonctionne pas non plus. Cela doit être fait à l'ancienne.
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
Que se passe-t-il si j'ai cascade = CascadeType.ALL, orphanRemoval = falseet supprime le parent? Va-t-il supprimer les enfants, même si j'ai spécifiquement dit de NE PAS le faire?
izogfif


7

vous pouvez utiliser @PrivateOwned pour supprimer les orphelins, par exemple

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

5
Merci @reshma, il convient de noter que @PrivateOwned est une extension JPA eclipselink.
Paul Whelan

5

Je trouve juste cette solution mais dans mon cas ça ne marche pas:

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

orphanRemoval = true n'a aucun effet.


1
J'avais besoin de nettoyer et de construire avant que le changement n'entre en vigueur.
maralbjo

Wow, je cherche depuis une heure pourquoi l'ajout de CascadeType.ALL sur mon ManyToOne ne faisait pas de suppressions en cascade. Nettoyé et construit et ça marche. Merci @maralbjo.
Andrew Mairose


2

J'ai eu le même problème et je me suis demandé pourquoi cette condition ci-dessous ne supprimait pas les orphelins. La liste des plats n'a pas été supprimée dans Hibernate (5.0.3.Final) lorsque j'ai exécuté une requête de suppression nommée:

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

Ensuite, je me suis souvenu que je ne devais pas utiliser une requête de suppression nommée , mais le EntityManager. Comme j'ai utilisé la EntityManager.find(...)méthode pour récupérer l'entité, puis EntityManager.remove(...)pour la supprimer, les plats ont également été supprimés.


2

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

Supprimez targetEntity = MyClass.class , cela fonctionne très bien.



0

J'utilisais un mappage un à un, mais l'enfant ne se faisait pas supprimer JPA donnait une violation de clé étrangère

Après avoir utilisé orphanRemoval = true, le problème a été résolu


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") enfant privé;
vipin chauhan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.