Da dies eine sehr häufige Frage ist, habe ich diesen Artikel geschrieben , auf dem diese Antwort basiert.
Übergänge des Entitätsstatus
JPA übersetzt Entitätsstatusübergänge in SQL-Anweisungen wie INSERT, UPDATE oder DELETE.
Wenn Sie persist
eine Entität sind, planen Sie, dass die INSERT-Anweisung ausgeführt wird, wenn sie EntityManager
automatisch oder manuell gelöscht wird.
Wenn Sie remove
eine Entität sind, planen Sie die DELETE-Anweisung, die ausgeführt wird, wenn der Persistenzkontext gelöscht wird.
Übergänge von kaskadierenden Entitätszuständen
Mit JPA können Sie Entitätsstatusübergänge von übergeordneten Entitäten zu untergeordneten Entitäten weitergeben.
Wenn Sie also eine übergeordnete Post
Entität haben, die mit der untergeordneten Entität @OneToMany
verknüpft istPostComment
:
Die comments
Sammlung in der Post
Entität wird wie folgt zugeordnet:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
CascadeType.ALL
Das cascade
Attribut weist den JPA-Anbieter an, den Entitätsstatusübergang von der übergeordneten Post
Entität an alle PostComment
in der comments
Auflistung enthaltenen Entitäten zu übergeben .
Wenn Sie also die Post
Entität entfernen :
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
Der JPA-Anbieter entfernt zuerst die PostComment
Entität. Wenn alle untergeordneten Entitäten gelöscht werden, wird auch die Post
Entität gelöscht :
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Waisenentfernung
Wenn Sie das orphanRemoval
Attribut auf festlegen true
, plant der JPA-Anbieter einen remove
Vorgang, wenn die untergeordnete Entität aus der Sammlung entfernt wird.
In unserem Fall also
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);
Der JPA-Anbieter wird den zugehörigen post_comment
Datensatz entfernen, da PostComment
in der comments
Sammlung nicht mehr auf die Entität verwiesen wird :
DELETE FROM post_comment WHERE id = 1
AUF KASKADE LÖSCHEN
Das ON DELETE CASCADE
ist auf FK-Ebene definiert:
ALTER TABLE post_comment
ADD CONSTRAINT fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE;
Wenn Sie dies tun, löschen Sie eine post
Zeile:
DELETE FROM post WHERE id = 1
Alle zugeordneten post_comment
Entitäten werden vom Datenbankmodul automatisch entfernt. Dies kann jedoch eine sehr gefährliche Operation sein, wenn Sie versehentlich eine Stammentität löschen.
Fazit
Der Vorteil von JPA cascade
und orphanRemoval
Optionen besteht darin, dass Sie auch von einer optimistischen Sperrung profitieren können , um verlorene Updates zu vermeiden .
Wenn Sie den JPA-Kaskadenmechanismus verwenden, müssen Sie keine DDL-Ebene verwenden. Dies ON DELETE CASCADE
kann eine sehr gefährliche Operation sein, wenn Sie eine Stammentität entfernen, die viele untergeordnete Entitäten auf mehreren Ebenen enthält.