web-dev-qa-db-fra.com

JPA 2.0 orphanRemoval = true VS à la suppression de Cascade

Je suis un peu confus à propos de l'attribut JPA 2.0 orphanRemoval.

Je pense comprendre que c'est nécessaire lorsque j'utilise les outils de génération de base de données de mon fournisseur JPA pour créer la base de données DDL sous-jacente afin de disposer d'un ON DELETE CASCADE sur la relation particulière.

Toutefois, si le DB existe et qu'il a déjà un ON DELETE CASCADE sur la relation, cela ne suffit-il pas pour castrer la suppression en cascade de manière appropriée? Que fait la orphanRemoval en plus?

À votre santé

159
Markos Fragkakis

orphanRemoval n'a rien à voir avec ON DELETE CASCADE.

orphanRemoval est un tout chose spécifique à l'ORM. Il marque que l'entité "enfant" doit être supprimée lorsqu'elle n'est plus référencée à partir de l'entité "parent", par exemple. lorsque vous supprimez l'entité enfant de la collection correspondante de l'entité parent.

ON DELETE CASCADE est un élément spécifique à la base de données, il supprime la ligne "enfant" de la base de données lorsque la ligne "parent" est supprimée.

245
axtavt

Un exemple de formulaire pris ici :

Lorsqu'un objet entité Employee est supprimé, l'opération de suppression est effectuée en cascade sur l'objet entité référencé Address. À cet égard, orphanRemoval=true et cascade=CascadeType.REMOVE sont identiques et si orphanRemoval=true est spécifié, CascadeType.REMOVE est redondant.

La différence entre les deux paramètres réside dans la réponse à la déconnexion d'une relation. Par exemple, lorsque vous définissez le champ d'adresse sur null ou sur un autre objet Address.

  • Si orphanRemoval=true est spécifié, l'instance déconnectée Address est automatiquement supprimée. Ceci est utile pour nettoyer des objets dépendants (par exemple Address) qui ne devraient pas exister sans une référence provenant d'un objet propriétaire (par exemple Employee).

  • Si seul cascade=CascadeType.REMOVE est spécifié, aucune action automatique n'est entreprise car la déconnexion d'une relation n'est pas une opération de suppression.

Pour éviter les suspensions de références résultant de la suppression d'Orphan, cette fonctionnalité ne doit être activée que pour les champs contenant des objets dépendants privés non partagés.

J'espère que cela rend les choses plus claires.

77
forhas

Dès que vous supprimez une entité enfant de la collection, vous supprimez également cette entité enfant de la base de données. orphanRemoval implique également que vous ne pouvez pas changer de parents; s'il y a un département qui a des employés, une fois que vous enlevez cet employé pour le placer dans un autre département, vous aurez par inadvertance supprimé cet employé de la base de données au moment de la mise à jour/du commit (selon la première éventualité). Le moral consiste à définir orphanRemoval sur true tant que vous êtes certain que les enfants de ce parent ne migreront pas vers un autre parent tout au long de leur existence. L'activation de orphanRemoval ajoute automatiquement REMOVE à la liste en cascade.

44
Onur

Le mappage JPA équivalent pour le DDL ON DELETE CASCADE est cascade=CascadeType.REMOVE. La suppression orpheline signifie que les entités dépendantes sont supprimées lorsque la relation avec leur entité "parent" est détruite. Par exemple, si un enfant est supprimé d'une relation @OneToMany sans le supprimer explicitement dans le gestionnaire d'entités.

17
Heri

La réponse de @GaryK est absolument géniale, j'ai passé une heure à chercher une explication orphanRemoval = true contre CascadeType.REMOVE et cela m'a aidé à comprendre.

En résumé: orphanRemoval = true fonctionne de la même manière que CascadeType.REMOVESEULEMENT SI nous supprimons un objet (entityManager.delete(object)) et nous souhaitons également supprimer les objets enfants.

Dans des situations complètement différentes, lorsque nous récupérons des données telles que List<Child> childs = object.getChilds(), puis retirons un enfant (entityManager.remove(childs.get(0)) à l'aide de orphanRemoval=true, l'entité correspondant à childs.get(0) sera supprimée de la base de données. .

4
pzeszko

La suppression d’orphelins a le même effet que ON DELETE CASCADE dans le scénario suivant: - Disons que nous avons une relation simple, plusieurs à un, entre une entité d’étudiant et une entité de guide, dans laquelle de nombreux étudiants peuvent être mappés vers le même guide. relation de clé étrangère entre Student et Table Guide telle que la table student porte id_guide comme FK.

    @Entity
    @Table(name = "student", catalog = "helloworld")
    public class Student implements Java.io.Serializable {
     @Id
     @GeneratedValue(strategy = IDENTITY)
     @Column(name = "id")
     private Integer id;

    @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
    @JoinColumn(name = "id_guide")
    private Guide guide;

// l'entité mère

    @Entity
    @Table(name = "guide", catalog = "helloworld")
    public class Guide implements Java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = 9017118664546491038L;

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;

@Column(name = "name", length = 45)
private String name;

@Column(name = "salary", length = 45)
private String salary;


 @OneToMany(mappedBy = "guide", orphanRemoval=true) 
 private Set<Student> students = new  HashSet<Student>(0);

Dans ce scénario, la relation est telle que l'entité étudiante est le propriétaire de la relation et, en tant que telle, nous devons sauvegarder l'entité étudiante afin de conserver le graphique d'objet entier, par exemple.

    Guide guide = new Guide("John", "$1500");
    Student s1 = new Student(guide, "Roy","ECE");
    Student s2 = new Student(guide, "Nick", "ECE");
    em.persist(s1);
    em.persist(s2);

Nous mappons ici le même guide avec deux objets étudiant différents et, étant donné que CASCADE.PERSIST est utilisé, le graphe d'objet sera enregistré comme suit dans la table de la base de données (MySql dans mon cas).

Table des étudiants: -

ID Nom Département Id_Guide

1 Roy ECE 1

2 Nick ECE 1

GUIDE Table: -

ID NOM Salaire

1 Jean 1500 $

et maintenant, si je veux supprimer un des étudiants, en utilisant

      Student student1 = em.find(Student.class,1);
      em.remove(student1);

et quand un dossier d’étudiant est supprimé, le dossier de guide correspondant doit également être supprimé, c’est là que l’attribut CASCADE.REMOVE de l’entité Étudiant entre en image et permet de supprimer l’élève avec l’identificateur 1 ainsi que l’objet guide correspondant (identificateur). 1). Mais dans cet exemple, un autre objet étudiant est mappé sur le même enregistrement de guide et, à moins d'utiliser l'attribut orphanRemoval = true dans l'entité de guide, le code de suppression ci-dessus ne fonctionnera pas.

3
kunal

La différence est:
- orphanRemoval = true: l'entité "enfant" est supprimée lorsqu'elle n'est plus référencée (son parent ne peut pas être supprimé).
- CascadeType.REMOVE: l'entité "enfant" est supprimée uniquement lorsque son "parent" est supprimé.

3
user3572554