Comme il s'agit d'une question très courante, j'ai écrit cet article , sur lequel cette réponse est basée.
Transitions d'état d'entité
JPA traduit les transitions d'état d'entité en instructions SQL, telles que INSERT, UPDATE ou DELETE.
Lorsque vous êtes persist
une entité, vous planifiez l'exécution de l'instruction INSERT lorsque le EntityManager
est vidé, automatiquement ou manuellement.
lorsque vous êtes remove
une entité, vous planifiez l'instruction DELETE, qui sera exécutée lorsque le contexte de persistance est vidé.
Transitions d'état d'entité en cascade
Pour plus de commodité, JPA vous permet de propager les transitions d'état d'entité des entités parentes vers les entités enfant.
Donc, si vous avez une Post
entité parente qui a une @OneToMany
association avec l' PostComment
entité enfant:
La comments
collection de l' Post
entité est mappée comme suit:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
CascadeType.ALL
L' cascade
attribut indique au fournisseur JPA de transmettre la transition d'état d'entité de l' Post
entité parente à toutes les PostComment
entités contenues dans la comments
collection.
Donc, si vous supprimez l' Post
entité:
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
Le fournisseur JPA supprimera d'abord l' PostComment
entité, et lorsque toutes les entités enfants seront supprimées, il supprimera également l' Post
entité:
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Élimination des orphelins
Lorsque vous définissez l' orphanRemoval
attribut sur true
, le fournisseur JPA va planifier une remove
opération lorsque l'entité enfant est supprimée de la collection.
Donc, dans notre cas,
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
PostComment postComment = post.getComments().get(0);
assertEquals(1L, postComment.getId());
post.getComments().remove(postComment);
Le fournisseur JPA va supprimer l' post_comment
enregistrement associé car l' PostComment
entité n'est plus référencée dans la comments
collection:
DELETE FROM post_comment WHERE id = 1
SUR SUPPRIMER LA CASCADE
Le ON DELETE CASCADE
est défini au niveau FK:
ALTER TABLE post_comment
ADD CONSTRAINT fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE;
Une fois que vous faites cela, si vous supprimez une post
ligne:
DELETE FROM post WHERE id = 1
Toutes les post_comment
entités associées sont supprimées automatiquement par le moteur de base de données. Cependant, cela peut être une opération très dangereuse si vous supprimez une entité racine par erreur.
Conclusion
L'avantage du JPA cascade
et des orphanRemoval
options est que vous pouvez également bénéficier d' un verrouillage optimiste pour éviter la perte de mises à jour .
Si vous utilisez le mécanisme de cascade JPA, vous n'avez pas besoin d'utiliser le niveau DDL ON DELETE CASCADE
, ce qui peut être une opération très dangereuse si vous supprimez une entité racine qui a de nombreuses entités enfants à plusieurs niveaux.
Pour plus de détails sur ce sujet, consultez cet article .