Оскільки це питання дуже поширене, ця відповідь базується на цій статті, яку я написав у своєму блозі.
CascadeType.REMOVE
CascadeType.REMOVE
Стратегія, яку ви можете налаштувати в явному вигляді:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();
або неявно успадкувати його від CascadeType.ALL
стратегії:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();
дозволяє розповсюдити remove
операцію від батьківської сутності до її дочірніх сутностей.
Отже, якщо ми дістаємо батьківську Post
сутність разом з її comments
колекцією та видаляємо post
сутність:
Post post = entityManager.createQuery("""
select p
from Post p
join fetch p.comments
where p.id = :id
""", Post.class)
.setParameter("id", postId)
.getSingleResult();
entityManager.remove(post);
Hibernate виконає три оператори видалення:
DELETE FROM post_comment
WHERE id = 2
DELETE FROM post_comment
WHERE id = 3
DELETE FROM post
WHERE id = 1
У PostComment
дочірніх об'єктах були видалені з-за CascadeType.REMOVE
стратегії, яка діяла , як якщо б ми прибрали дочірні об'єкти , а також.
Стратегія вилучення сиріт
Стратегія вилучення сиріт, яку потрібно встановити через orphanRemoval
атрибут:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
дозволяє видалити рядок дочірньої таблиці після видалення дочірньої сутності з колекції.
Отже, якщо ми завантажимо Post
сутність разом із її comments
колекцією та видалимо першу PostComment
з comments
колекції:
Post post = entityManager.createQuery("""
select p
from Post p
join fetch p.comments c
where p.id = :id
order by p.id, c.id
""", Post.class)
.setParameter("id", postId)
.getSingleResult();
post.remove(post.getComments().get(0));
Hibernate виконує оператор DELETE для відповідного post_comment
рядка таблиці:
DELETE FROM post_comment
WHERE id = 2
Докладніше про цю тему також ознайомтесь із цією статтею .