테스트 코드
var newChannel = Channel.builder().name("new-channel").build();
var newThread = Thread.builder().message("new-message").build();
var newThread1 = Thread.builder().message("장마 끝!!").build();
newThread.setChannel(newChannel);
newThread1.setChannel(newChannel);
var savedChannel = channelRepository.insertChannel(newChannel);
var savedThread = threadRepository.insertThread(newThread);
var savedThread1 = threadRepository.insertThread(newThread1);
// when
var foundChannel = channelRepository.selectChannel(savedChannel.getId());
foundChannel.getThreads().remove(savedThread);
1. CascadeType.ALL만 적용한 경우
@OneToMany(mappedBy = "channel", cascade = CascadeType.ALL)
private Set<Thread> threads = new LinkedHashSet<>(); // 중복 x 순서 o
Hibernate:
insert
into
channel
(name, type)
values
(?, ?)
Hibernate:
insert
into
thread
(channel_id, message)
values
(?, ?)
Hibernate:
insert
into
thread
(channel_id, message)
values
(?, ?)
delete 쿼리가 날아가지 않는다.
2. CascadeType.ALL과 orphanRemoval = true 둘 다 적용한 경우
@OneToMany(mappedBy = "channel", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Thread> threads = new LinkedHashSet<>(); // 중복 x 순서 o
Hibernate:
insert
into
channel
(name, type)
values
(?, ?)
Hibernate:
insert
into
thread
(channel_id, message)
values
(?, ?)
Hibernate:
insert
into
thread
(channel_id, message)
values
(?, ?)
Hibernate:
delete
from
thread
where
id=?
delete 쿼리가 날아가고 스레드 테이블에서 스레드가 삭제된다.
3. orphanRemoval = true 만 적용한 경우
Hibernate:
insert
into
channel
(name, type)
values
(?, ?)
Hibernate:
insert
into
thread
(channel_id, message)
values
(?, ?)
Hibernate:
insert
into
thread
(channel_id, message)
values
(?, ?)
delete 쿼리가 날라가지 않는다.
Cascade.REMOVE 와 orphanRemoval 차이점
Cascade.REMOVE : 부모 엔티티를 em.remove로 직접 삭제하면 자식 엔티티도 삭제된다.
orphanRemoval : 부모 엔티티를 em.remove로 직접 삭제하면 자식 엔티티도 삭제된다. + 부모 엔티티의 리스트에서 어떤 요소를 삭제하면 그에 해당하는 자식 엔티티도 삭제된다. 즉, 리스트 요소의 영속성 전이도 해준다.
위 테스트 코드로 예를 들면 부모 객체인 savedChannel의 threads 안에 있는 savedThread를 제거하면 스레드 테이블에서도 해당 스레드가 삭제된다.
영속성 전이 최강 조합 : CascadeType.ALL + orphanRemoval = true
위 두가지를 함께 설정하면 자식 엔티티의 라이프 사이클이 부모 엔티티와 동일해지며, 직접 자식 엔티티의 생명주기를 관리할 수 있게 되므로 자식 엔티티의 Repository 조차 없어도 된다. (따라서, 매핑 테이블에서 많이 쓰임)
Fetch(조회 시점)
FetchType
EAGER : 부모 조회 시 자식도 같이 조회
LAZY : 부모 조회시 부모만 조회, 자식은 필요할 때 따로 조회
'내배캠 TIL > WEEK11' 카테고리의 다른 글
equals()로 객체 비교 (0) | 2023.07.25 |
---|