251 votes

Quelle est la signification de CascadeType.ALL pour une association JPA @ManyToOne ?

Je pense que j'ai mal compris la signification de la mise en cascade dans le contexte d'une @ManyToOne relation.

L'affaire :

public class User {

   @OneToMany(fetch = FetchType.EAGER)
   protected Set<Address> userAddresses;

}

public class Address {

   @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
   protected User addressOwner;

}

Quelle est la signification de la cascade = CascadeType.ALL ? Par exemple, si je supprime une certaine adresse de la base de données, comment le fait que j'ai ajouté l'adresse en question à la base de données peut-il être pris en compte ? cascade = CascadeType.ALL affectent mes données (le User (je suppose) ?

411voto

kostja Points 20153

La signification de CascadeType.ALL est que la persistance propage (en cascade) toutes les EntityManager les opérations ( PERSIST, REMOVE, REFRESH, MERGE, DETACH ) aux entités concernées.

Dans votre cas, il semble que ce soit une mauvaise idée, car la suppression d'une Address conduirait à la suppression de la User . Comme un utilisateur peut avoir plusieurs adresses, les autres adresses deviennent orphelines. Cependant, le cas inverse (annotation des User ) serait logique - si une adresse n'appartient qu'à un seul utilisateur, il est sûr de propager la suppression de toutes les adresses appartenant à un utilisateur si celui-ci est supprimé.

BTW : vous pouvez ajouter un mappedBy="addressOwner" à votre User pour signaler au fournisseur de persistance que la colonne de jonction doit se trouver dans la table ADDRESS.

7 votes

Il pourrait être bon d'avoir CascadeType.ALL du côté de @OneToMany cependant.

55voto

seba.wagner Points 1668

Voir ici pour un exemple tiré de la documentation d'OpenJPA. CascadeType.ALL signifie qu'il fera toutes les actions.

Citation :

CascadeType.PERSIST : Lorsque vous persistez une entité, persistez également les entités contenues dans ses champs. Nous suggérons une application libérale de cette règle de cascade, car si l'EntityManager trouve un champ qui fait référence à une nouvelle entité pendant le flush, et que le champ n'utilise pas CascadeType.PERSIST, c'est une erreur.

CascadeType.REMOVE : Lorsque l'on supprime une entité, on supprime également les entités contenues dans ce champ.

CascadeType.REFRESH : Lors de l'actualisation d'une entité, les entités contenues dans ce champ sont également actualisées.

CascadeType.MERGE : Lorsque l'on fusionne l'état de l'entité, on fusionne également les entités contenues dans ce champ.

Sebastian

4 votes

Nouveau dans JPA, cette information est utile mais qu'en est-il de Detach ici ?

1 votes

Dans CascadeType.DETACH, lorsqu'on détache une entité, em détache également les entités détenues par l'entité mère.

54voto

Vlad Mihalcea Points 3628

Vous ne devriez pas utiliser CascadeType.ALL sur @ManyToOne puisque les transitions d'état des entités doivent se propager des entités mères aux entités filles, et non l'inverse.

Le site @ManyToOne est toujours l'association Enfant, car elle met en correspondance la colonne de clé étrangère sous-jacente.

Par conséquent, vous devez déplacer le CascadeType.ALL de la @ManyToOne l'association à la @OneToMany qui devrait également utiliser le mappedBy car il s'agit du mappage de la relation de table un à plusieurs le plus efficace.

1 votes

Merci Vlad, je ne sais pas pourquoi ce n'est pas une réponse prioritaire.

20voto

Kevin Bowersox Points 48223

Extrait de la spécification EJB3.0 :

L'utilisation de l'élément d'annotation cascade peut être utilisée pour propager l'effet d'une opération aux entités associées. l'effet d'une opération aux entités associées. La fonctionnalité de cascade est le plus souvent utilisée dans les relations parent-enfant.

Si X est une entité gérée, l'opération de suppression la fait devenir supprimée. L'opération de suppression est répercutée en cascade sur les entités référencées par X, si les relations entre X et ces autres entités sont annotées par la valeur de l'élément d'annotation la valeur de l'élément d'annotation cascade=REMOVE ou cascade=ALL.

Donc, en résumé, les relations entre entités définies avec CascadeType.All garantira que tous les événements de persistance tels que persist, refresh, merge et remove qui se produisent sur le parent, seront transmis à l'enfant. Définir d'autres CascadeType fournit au développeur un niveau de contrôle plus granulaire sur la façon dont l'association d'entités gère la persistance.

Par exemple, si j'ai un objet Livre qui contient une liste de pages et que j'ajoute un objet page dans cette liste. Si l'objet @OneToMany L'annotation définissant l'association entre le livre et la page est marquée en tant que CascadeType.All En effet, la persistance du livre entraînerait la persistance de la page dans la base de données.

12voto

Emilien Brigand Points 35

En JPA 2.0, si vous voulez supprimer une adresse si vous l'avez retirée d'une entité Utilisateur, vous pouvez ajouter orphanRemoval=true (au lieu de CascadeType.REMOVE ) à votre @OneToMany .

Plus d'explications entre orphanRemoval=true et CascadeType.REMOVE est ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X