Zustandsübergänge von Entitäten
JPA übersetzt Zustandsübergänge von Entitäten in SQL-Anweisungen wie INSERT, UPDATE oder DELETE.
![Zustandsübergänge von JPA-Entitäten]()
Wenn Sie eine Entität persistieren
, planen Sie die Ausführung der INSERT-Anweisung, wenn der EntityManager
automatisch oder manuell geflusht wird.
Wenn Sie eine Entität entfernen
, planen Sie die DELETE-Anweisung, die ausgeführt wird, wenn der Persistenzkontext geflusht wird.
Kaskadierende Zustandsübergänge von Entitäten
Zu Ihrer Bequemlichkeit erlaubt JPA das Weiterleiten von Zustandsübergängen von Elternentitäten zu Kindentitäten.
Also, wenn Sie eine Elternentität Post
haben, die eine @OneToMany
-Assoziation mit der Kindentität PostComment
hat:
![Post- und PostComment-Entitäten]()
Die comments
-Sammlung in der Entität Post
ist wie folgt gemappt:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List comments = new ArrayList<>();
CascadeType.ALL
Das cascade
-Attribut sagt dem JPA-Anbieter, die Zustandsübergänge der Elternentität Post
auf alle PostComment
-Entitäten weiterzuleiten, die in der comments
-Sammlung enthalten sind.
Also, wenn Sie die Post
-Entität entfernen:
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
Der JPA-Anbieter wird zuerst die PostComment
-Entität entfernen, und wenn alle Kindentitäten gelöscht sind, wird er auch die Post
-Entität löschen:
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Orphan removal
Wenn Sie das orphanRemoval
-Attribut auf true
setzen, plant der JPA-Anbieter eine remove
-Operation, wenn die Kindentität aus der Sammlung entfernt wird.
Also, in unserem Fall,
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 die PostComment
-Entität nicht mehr in der comments
-Sammlung referenziert wird:
DELETE FROM post_comment WHERE id = 1
ON DELETE CASCADE
Das ON DELETE CASCADE
wird auf der 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 das tun, und eine post
-Zeile löschen:
DELETE FROM post WHERE id = 1
Werden automatisch alle zugehörigen post_comment
-Entitäten von der Datenbank-Engine entfernt. Dies kann jedoch eine sehr gefährliche Operation sein, wenn Sie versehentlich eine Stamm-Entität löschen.
Fazit
Der Vorteil der JPA-Optionen cascade
und orphanRemoval
ist, dass Sie auch von optimistischem Sperren profitieren können, um verlorene Updates zu verhindern.
Wenn Sie den JPA-Kaskadierungsmechanismus verwenden, müssen Sie nicht das DDl-Level ON DELETE CASCADE
verwenden, was eine sehr gefährliche Operation sein kann, wenn Sie eine Stamm-Entität löschen, die viele Kind-Entitäten auf mehreren Ebenen hat.