139 votes

Quelle est la différence entre CascadeType.REMOVE et orphanRemoval dans JPA ?

Quelle est la différence entre

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

et

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

Cet exemple est tiré du Java EE Tutorial, mais je ne comprends toujours pas les détails.

172voto

Rahul Tripathi Points 1

De aquí :-

Suppression en cascade

Le fait de marquer un champ de référence avec CascadeType.REMOVE (ou CascadeType.ALL, qui inclut REMOVE) indique que les opérations de suppression doivent être automatiquement aux objets d'entité qui sont référencés par ce champ (plusieurs (plusieurs objets d'entité peuvent être référencés par un champ de collection). de collection) :

@Entity
class Employee {
     :
    @OneToOne(cascade=CascadeType.REMOVE)
    private Address address;
     :
}

Suppression des orphelins

JPA 2 supporte un mode de suppression en cascade supplémentaire et plus agressif qui peut être spécifié en utilisant l'élément orphanRemoval des annotations @OneToOne et @OneToMany :

@Entity
class Employee {
     :
    @OneToOne(orphanRemoval=true)
    private Address address;
     :
}

DIFFERENCE:-

La différence entre les deux réglages se situe dans la réponse à déconnexion d'une relation. Par exemple, lorsque le champ champ adresse à null ou à un autre objet Adresse.

  • Si orphanRemoval=true est spécifié, l'instance d'adresse déconnectée est automatiquement supprimée. Ceci est utile pour nettoyer objets dépendants (par exemple Adresse) qui ne doivent pas exister sans une référence référence à un objet propriétaire (par exemple, Employee).
  • Si seulement cascade=CascadeType.REMOVE est spécifié, aucune action automatique n'est prise puisque la déconnexion d'une relation n'est pas une suppression.
    fonctionnement.

116voto

study Points 4336

Une façon simple de comprendre la différence entre CascadeType.REMOVE y orphanRemoval=true .

Pour le retrait des orphelins : Si vous invoquez setOrders(null) , les Order Les entités seront supprimées automatiquement dans la base de données.

Pour enlever la cascade : Si vous invoquez setOrders(null) , les Order les entités seront PAS seront supprimés automatiquement dans la base de données.

29voto

user3593084 Points 42

Supposons que nous ayons une entité enfant et une entité parent. Un parent peut avoir plusieurs enfants.

@Entity
class parent {
  //id and other fields
 @OneToMany (orphanRemoval = "true",cascade = CascadeType.REMOVE)
   Set<Person> myChildern;
}

L'orphanRemoval est un concept ORM, il indique si l'enfant est orphelin. Il doit également être supprimé de la base de données.

Un enfant est orphelin lorsqu'il n'est pas accessible depuis son parent. Par exemple, si nous supprimons l'ensemble d'objets Personne (en lui donnant la valeur d'un ensemble vide) ou si nous le remplaçons par un nouvel ensemble, le parent ne peut plus accéder aux enfants de l'ancien ensemble et les enfants sont orphelins ; ils sont donc condamnés à être supprimés dans la base de données également.

CascadeType.REMOVE est un concept au niveau de la base de données. Il indique que si le parent est supprimé, tous les enregistrements qui lui sont liés dans la table enfant doivent être supprimés.

17voto

Vlad Mihalcea Points 3628

CascadeType.REMOVE

El CascadeType.REMOVE stratégie, que vous pouvez configurer explicitement :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();

ou l'hériter implicitement de la CascadeType.ALL stratégie :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();

vous permet de propager le remove de l'entité mère vers ses entités filles.

Donc, si nous récupérons le parent Post ainsi que son comments et supprimez la collection post entité :

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments
    where p.id = :id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

entityManager.remove(post);

Hibernate va exécuter trois instructions de suppression :

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

El PostComment les entités enfant ont été supprimées à cause de la CascadeType.REMOVE qui a agi comme si nous avions également supprimé les entités enfants.

La stratégie de suppression des orphelins

La stratégie de suppression des orphelins, qui doit être définie via l'option orphanRemoval attribut :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

vous permet de supprimer la ligne de la table enfant lors de la suppression de l'entité enfant de la collection.

Donc, si nous chargeons le Post ainsi que son comments et supprimer le premier PostComment de la comments collection :

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments c
    where p.id = :id
    order by p.id, c.id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

post.remove(post.getComments().get(0));

Hibernate va exécuter une instruction DELETE pour les données associées. post_comment ligne de table :

DELETE FROM post_comment 
WHERE id = 2

5voto

garg10may Points 2698

En pratique, la différence réside dans le fait que vous essayez de mettre à jour les données (PATCH) ou de les remplacer entièrement (PUT).

Disons que vous supprimez le customer que d'utiliser cascade=REMOVE supprimera également les commandes de ce client qui semblent voulues et utiles.

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

Maintenant, disons que vous mettez à jour un customer con orphanRemoval="true" il supprimera toutes les commandes précédentes et les remplacera par celle fournie. ( PUT en termes de REST API )

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

Sans orphanRemoval les anciennes commandes seraient conservées. ( PATCH en termes de REST API )

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