테스트 코드

        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

+ Recent posts