Como esta es una pregunta muy común, escribí este artículo , en el que se basa esta respuesta.
Transiciones de estado de entidad
JPA traduce las transiciones de estado de la entidad a sentencias SQL, como INSERT, UPDATE o DELETE.
Cuando usted es persist
una entidad, está programando la instrucción INSERT para que se ejecute cuando EntityManager
se vacía, de forma automática o manual.
cuando eres remove
una entidad, estás programando la declaración DELETE, que se ejecutará cuando se vacíe el Contexto de persistencia.
Transiciones de estado de entidad en cascada
Por conveniencia, JPA le permite propagar las transiciones de estado de la entidad de las entidades principales a las secundarias.
Entonces, si tiene una Post
entidad principal que tiene una @OneToMany
asociación con la PostComment
entidad secundaria:
La comments
colección en la Post
entidad se asigna de la siguiente manera:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
CascadeType.ALL
El cascade
atributo le dice al proveedor de JPA que pase la transición del estado de la Post
entidad de la entidad principal a todas las PostComment
entidades contenidas en elcomments
colección.
Entonces, si elimina la Post
entidad:
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
El proveedor de JPA eliminará PostComment
primero la entidad, y cuando se eliminen todas las entidades secundarias, también eliminará la Post
entidad:
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Retiro de huérfanos
Cuando establezca el orphanRemoval
atributo en true
, el proveedor de JPA programará una remove
operación cuando la entidad secundaria se elimine de la colección.
Entonces, en nuestro 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);
El proveedor de JPA eliminará el post_comment
registro asociado ya que la PostComment
entidad ya no está referenciada en la comments
colección:
DELETE FROM post_comment WHERE id = 1
EN ELIMINAR CASCADA
El ON DELETE CASCADE
se define en el nivel FK:
ALTER TABLE post_comment
ADD CONSTRAINT fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE;
Una vez que haga eso, si elimina una post
fila:
DELETE FROM post WHERE id = 1
El post_comment
motor de la base de datos elimina automáticamente todas las entidades asociadas . Sin embargo, esta puede ser una operación muy peligrosa si elimina una entidad raíz por error.
Conclusión
La ventaja de JPA cascade
y las orphanRemoval
opciones es que también puede beneficiarse del bloqueo optimista para evitar actualizaciones perdidas .
Si usa el mecanismo de cascada JPA, no necesita usar el nivel DDL ON DELETE CASCADE
, que puede ser una operación muy peligrosa si elimina una entidad raíz que tiene muchas entidades secundarias en varios niveles.
Para obtener más detalles sobre este tema, consulte este artículo .