영속성 전이를 통해 하나의 Entity가 생성, 업데이트 될 때 하위 Entity도 같이 생성, 업데이트 해주는 방법이다.
연관관계가 없어진 Entity를 제거
Cascade remove
Orphan Removal
기본 book, publisher 데이터
book : Book(super=BaseEntity(createdAt=2022-12-21T04:28:48.567497500, updatedAt=2022-12-21T04:28:49.084049600), id=1, name=JPA Book1)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:28:48.733219300, updatedAt=2022-12-21T04:28:49.086049300), id=2, name=JPA Book2)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:28:48.738221100, updatedAt=2022-12-21T04:28:49.086049300), id=3, name=JPA Book3)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:28:48.744382600, updatedAt=2022-12-21T04:28:49.087054), id=4, name=JPA Book4)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:28:48.764383900, updatedAt=2022-12-21T04:28:48.764383900), id=1, name=Go Study)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:28:48.799388600, updatedAt=2022-12-21T04:28:48.799388600), id=2, name=Stop Study)
Book Id 1's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:28:48.764383900, updatedAt=2022-12-21T04:28:48.764383900), id=1, name=Go Study)
Book Id 2's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:28:48.764383900, updatedAt=2022-12-21T04:28:48.764383900), id=1, name=Go Study)
Book Id 3's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:28:48.799388600, updatedAt=2022-12-21T04:28:48.799388600), id=2, name=Stop Study)
Book Id 4's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:28:48.799388600, updatedAt=2022-12-21T04:28:48.799388600), id=2, name=Stop Study)
publisherRepository.deleteById(1L);
book : Book(super=BaseEntity(createdAt=2022-12-21T04:44:35.479485, updatedAt=2022-12-21T04:44:35.479485), id=3, name=JPA Book3)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:44:35.482511, updatedAt=2022-12-21T04:44:35.609654), id=4, name=JPA Book4)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:44:35.475482, updatedAt=2022-12-21T04:44:35.475482), id=2, name=Stop Study)
Book Id 3's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:44:35.475482, updatedAt=2022-12-21T04:44:35.475482), id=2, name=Stop Study)
Book Id 4's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:44:35.475482, updatedAt=2022-12-21T04:44:35.475482), id=2, name=Stop Study)
연결관계 삭제 코드
Publisher publisher = publisherRepository.findById(1L).get();
publisher.getBooks().remove(0);
publisherRepository.save(publisher);
book : Book(super=BaseEntity(createdAt=2022-12-21T04:50:22.094850, updatedAt=2022-12-21T04:50:22.358255), id=1, name=JPA Book1)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:50:22.113942, updatedAt=2022-12-21T04:50:22.359602), id=2, name=JPA Book2)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:50:22.125450, updatedAt=2022-12-21T04:50:22.360635), id=3, name=JPA Book3)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:50:22.132505, updatedAt=2022-12-21T04:50:22.360635), id=4, name=JPA Book4)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:50:21.920055, updatedAt=2022-12-21T04:50:21.920055), id=1, name=Go Study)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:50:22.119936, updatedAt=2022-12-21T04:50:22.119936), id=2, name=Stop Study)
Book Id 1's publisher : null
Book Id 2's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:50:21.920055, updatedAt=2022-12-21T04:50:21.920055), id=1, name=Go Study)
Book Id 3's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:50:22.119936, updatedAt=2022-12-21T04:50:22.119936), id=2, name=Stop Study)
Book Id 4's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:50:22.119936, updatedAt=2022-12-21T04:50:22.119936), id=2, name=Stop Study)
연결 관계 삭제로 book 1의 연결관계는 삭제 되었다.
연결 관계가 삭제 되어도 자식 Entity까지 삭제 되지는 않는다.
book : Book(super=BaseEntity(createdAt=2022-12-21T04:54:49.058277, updatedAt=2022-12-21T04:54:49.283524), id=2, name=JPA Book2)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:54:49.070049, updatedAt=2022-12-21T04:54:49.284522), id=3, name=JPA Book3)
book : Book(super=BaseEntity(createdAt=2022-12-21T04:54:49.075048, updatedAt=2022-12-21T04:54:49.284522), id=4, name=JPA Book4)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:54:48.859726, updatedAt=2022-12-21T04:54:48.859726), id=1, name=Go Study)
publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:54:49.063654, updatedAt=2022-12-21T04:54:49.063654), id=2, name=Stop Study)
Book Id 2's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:54:48.859726, updatedAt=2022-12-21T04:54:48.859726), id=1, name=Go Study)
Book Id 3's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:54:49.063654, updatedAt=2022-12-21T04:54:49.063654), id=2, name=Stop Study)
Book Id 4's publisher : Publisher(super=BaseEntity(createdAt=2022-12-21T04:54:49.063654, updatedAt=2022-12-21T04:54:49.063654), id=2, name=Stop Study)
Book 1
이 삭제된 것을 확인 할 수 있다.CascadeType.REMOVE
와 orphanRemoval=true
는 부모 엔티티를 삭제하면 자식 엔티티도 삭제한다.CascadeType.REMOVE
는 자식 엔티티가 그대로 남아있는 반면, orphanRemoval=true
는 자식 엔티티를 제거한다.실제 운용환경에서 delete 방식은 위험성이 있으므로 자주 사용되는 방식은 아니다. 따라서, 소프트웨어적으로 delete 되었다로만 처리하는 경우가 많다.
따라서, DB에서는 값이 존재하지만 Logic 상에서는 값이 존재하지 않는 것으로 처리하는 것이다.
@Entity
@Where(clause = "deleted = false")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String category;
private Long authorId;
@ToString.Exclude
private boolean deleted; // true : deleted, false : not deleted
}
@Where
Annotation을 붙이고 deleted=false 옵션을 사용하면 JPA 쿼리문에 항상 where deleted = false
문이 붙게 된다.