215 votes

Quelle est la différence entre la clause JPA orphanRemoval=true et la clause DML ON DELETE CASCADE ?

Je suis un peu confus au sujet de la JPA 2.0 orphanRemoval attribut.

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

Cependant, si la base de données existe et qu'elle possède déjà un numéro d'identification de la base de données. ON DELETE CASCADE sur la relation, n'est-ce pas suffisant pour cascader la suppression de manière appropriée ? Que fait le orphanRemoval faire en plus ?

Cheers

15voto

user3572554 Points 141

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é.

6voto

pzeszko Points 602

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

En résumé : orphanRemoval = true fonctionne de manière identique à CascadeType.REMOVE UNIQUEMENT SI nous supprimons l'objet ( entityManager.delete(object) ) et nous voulons que les objets enfants soient également supprimés.

Dans une situation complètement différente, lorsque nous récupérons des données telles que List<Child> childs = object.getChilds() et ensuite retirer un enfant ( entityManager.remove(childs.get(0) ) en utilisant orphanRemoval=true fera en sorte que l'entité correspondant à childs.get(0) sera supprimé de la base de données.

1 votes

Vous avez une coquille dans votre deuxième paragraphe : La méthode entityManager.delete(obj) n'existe pas ; c'est entityManager.remove(obj).

3voto

kunal Points 83

La suppression orpheline a le même effet que l'opération ON DELETE CASCADE dans le scénario suivant Disons que nous avons une relation simple de plusieurs à un entre l'entité étudiant et l'entité guide, où de nombreux étudiants peuvent être associés au même guide et dans la base de données nous avons une relation de clé étrangère entre la table étudiant et la table guide telle que la table étudiant a 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é étudiant est le propriétaire de la relation et en tant que tel, nous devons sauvegarder l'entité étudiant afin de persister le graphe d'objets 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);

Ici, nous mappons le même guide avec deux objets étudiants différents et puisque CASCADE.PERSIST est utilisé, le graphique des objets sera enregistré comme ci-dessous dans la table de la base de données (MySql dans mon cas).

Table d'étudiant:-

ID Nom Dépt Id_Guide

1 Roy ECE 1

2 Nick ECE 1

GUIDE Table:-

ID NOM Salaire

1 John $1500

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

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

et lorsqu'un enregistrement d'étudiant est supprimé, l'enregistrement de guide correspondant doit également être supprimé, c'est là que l'attribut CASCADE.REMOVE de l'entité Student entre en jeu et ce qu'il fait est ;il supprime l'étudiant avec l'identifiant 1 ainsi que l'objet guide correspondant (identifiant 1). Mais dans cet exemple, il y a un autre objet étudiant qui est associé au même enregistrement de guide et à moins que nous n'utilisions l'attribut orphanRemoval=true dans l'entité Guide, le code de suppression ci-dessus ne fonctionnera pas.

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