Poiché questa è una domanda molto comune, ho scritto questo articolo , su cui si basa questa risposta.
Transizioni dello stato delle entità
JPA traduce le transizioni dello stato dell'entità in istruzioni SQL, come INSERT, UPDATE o DELETE.
Quando si è persist
un'entità, si sta pianificando che l'istruzione INSERT venga eseguita quando EntityManager
viene scaricata, automaticamente o manualmente.
quando sei remove
un'entità, stai pianificando l'istruzione DELETE, che verrà eseguita quando il Contesto di persistenza viene svuotato.
Transizioni di stato entità a cascata
Per comodità, JPA consente di propagare le transizioni di stato delle entità da entità padre a quella figlio.
Pertanto, se si dispone di Post
un'entità padre che ha @OneToMany
un'associazione con l' PostComment
entità figlio:
La comments
raccolta Post
nell'entità è mappata come segue:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
CascadeType.ALL
L' cascade
attributo indica al provider JPA di passare la transizione dello stato dell'entità Post
dall'entità padre a tutte le PostComment
entità contenute incomments
raccolta.
Quindi, se rimuovi l' Post
entità:
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
Il provider JPA rimuoverà PostComment
prima l' entità e quando tutte le entità figlio verranno eliminate, eliminerà anche l' Post
entità:
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Rimozione orfana
Quando si imposta l' orphanRemoval
attributo su true
, il provider JPA pianificherà remove
un'operazione quando l'entità figlio viene rimossa dalla raccolta.
Quindi, nel nostro caso,
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);
Il provider JPA rimuoverà il post_comment
record associato poiché l' PostComment
entità non fa più riferimento nella comments
raccolta:
DELETE FROM post_comment WHERE id = 1
ALLA CANCELLAZIONE DELLA CASCATA
Il ON DELETE CASCADE
è definito a livello FK:
ALTER TABLE post_comment
ADD CONSTRAINT fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE;
Una volta che lo fai, se elimini una post
riga:
DELETE FROM post WHERE id = 1
Tutte le post_comment
entità associate vengono rimosse automaticamente dal motore di database. Tuttavia, questa operazione può essere molto pericolosa se si elimina un'entità radice per errore.
Conclusione
Il vantaggio dell'APP cascade
e delle orphanRemoval
opzioni è che puoi anche trarre vantaggio dal blocco ottimistico per evitare la perdita di aggiornamenti .
Se si utilizza il meccanismo a cascata JPA, non è necessario utilizzare il livello DDL ON DELETE CASCADE
, che può essere un'operazione molto pericolosa se si rimuove un'entità radice che ha molte entità figlio su più livelli.
Per maggiori dettagli su questo argomento, consulta questo articolo .