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.

Paul Whelan
la source

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)
Varun Mehta
la source
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.

Kango_V
la source
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                                               
╚═════════════╩═════════════════════╩═════════════════════╝
Sergii Shevchyk
la source
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;
reshma
la source
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.

Valéry Stroeder
la source
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
4

Selon Java Persistence with Hibernate , la suppression d'orphelin en cascade n'est pas disponible en tant qu'annotation JPA.

Il n'est pas non plus pris en charge dans JPA XML.

boîte à outils
la source
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.

Bevor
la source
2

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

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

Kohan95
la source
1

Pour mémoire, dans OpenJPA avant JPA2, c'était @ElementDependant.

Simone Gianni
la source
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

vipin chauhan
la source
@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") enfant privé;
vipin chauhan