Vì đây là một câu hỏi rất phổ biến, tôi đã viết bài viết này , trên đó câu trả lời này dựa trên.
Thực thể chuyển trạng thái
JPA dịch các chuyển đổi trạng thái thực thể sang các câu lệnh SQL, như INSERT, UPDATE hoặc DELETE.
Khi bạn persist
là một thực thể, bạn đang lên lịch cho câu lệnh INSERT được thực thi khi được xóa EntityManager
, tự động hoặc thủ công.
Khi bạn remove
là một thực thể, bạn đang lên lịch cho câu lệnh DELETE, nó sẽ được thực thi khi Bối cảnh liên tục bị xóa.
Chuyển trạng thái thực thể xếp chồng
Để thuận tiện, JPA cho phép bạn tuyên truyền chuyển trạng thái thực thể từ thực thể cha sang con.
Vì vậy, nếu bạn có một Post
thực thể cha mẹ có @OneToMany
liên kết với PostComment
thực thể con:
Bộ comments
sưu tập trong Post
thực thể được ánh xạ như sau:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
CascadeType.ALL
Các cascade
thuộc tính nói với các nhà cung cấp JPA để vượt qua sự chuyển đổi trạng thái thực thể từ cha mẹ Post
tổ chức cho tất cả PostComment
các đối tượng chứa trong comments
bộ sưu tập.
Vì vậy, nếu bạn loại bỏ Post
thực thể:
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
Nhà cung cấp JPA sẽ xóa PostComment
thực thể trước và khi tất cả các thực thể con bị xóa, nó cũng sẽ xóa Post
thực thể đó:
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Loại bỏ mồ côi
Khi bạn đặt orphanRemoval
thuộc tính thành true
, nhà cung cấp JPA sẽ lên lịch remove
hoạt động khi thực thể con bị xóa khỏi bộ sưu tập.
Vì vậy, trong trường hợp của chúng tôi,
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);
Nhà cung cấp JPA sẽ xóa post_comment
bản ghi liên quan do PostComment
thực thể không còn được tham chiếu trong comments
bộ sưu tập:
DELETE FROM post_comment WHERE id = 1
TRÊN CASCADE XÓA
Các ON DELETE CASCADE
được xác định ở cấp FK:
ALTER TABLE post_comment
ADD CONSTRAINT fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE;
Khi bạn làm điều đó, nếu bạn xóa một post
hàng:
DELETE FROM post WHERE id = 1
Tất cả các post_comment
thực thể liên quan được loại bỏ tự động bởi công cụ cơ sở dữ liệu. Tuy nhiên, đây có thể là một hoạt động rất nguy hiểm nếu bạn xóa nhầm một thực thể gốc.
Phần kết luận
Ưu điểm của JPA cascade
và orphanRemoval
các tùy chọn là bạn cũng có thể hưởng lợi từ việc khóa lạc quan để ngăn chặn các cập nhật bị mất .
Nếu bạn sử dụng cơ chế xếp tầng JPA, bạn không cần sử dụng cấp độ DDL ON DELETE CASCADE
, đây có thể là một hoạt động rất nguy hiểm nếu bạn xóa một thực thể gốc có nhiều thực thể con ở nhiều cấp độ.