Spring

[Spring] Cascade관계에서 추가로 활용하면 좋을 옵션 orphanRemoval

퉁그리 2022. 1. 18. 22:16

cascade에는 remove라는 옵션이 있다.

이는 부모 엔티티가 삭제되면 자식 엔티티가 삭제되는 옵션이다.

즉 부모가 자식의 삭제 생명주기를 관리하게 되는 것이다.

cascade의 persist까지 쓰게 된다면, 부모가 자식의 전체 생명주기를 관리하게 된다.

 

하지만 이 옵션들에는 구멍이 있는데, 바로 부모자식관계를 끊어 냈을 때 즉, 고아를 만들었을 때 삭제되지 않는다.

 

orphanRemoval 옵션없이 cascasde 옵션만 설정했을 때 자식관계를 끊어내봤다.

// JpaLearningTest.java
@DisplayName("CascadeType.REMOVE - 부모 엔티티(Team)에서 자식 엔티티(Member)를 제거하는 경우")
@Test
void cascadeType_Remove_InCaseOfMemberRemovalFromTeam() {
    // given
    Member member1 = new Member();
    Member member2 = new Member();

    Team team = new Team();

    team.addMember(member1);
    team.addMember(member2);

    teamRepository.save(team);

    // when
    team.getMembers().remove(0);

    // then
    List<Team> teams = teamRepository.findAll();
    List<Member> members = memberRepository.findAll();

    assertThat(teams).hasSize(1);
    assertThat(members).hasSize(2);
}

orphanRemoval

나가는 쿼리는 이와같다.

// DML
Hibernate: 
    insert 
    into
        team
        (id, name) 
    values
        (null, ?)
Hibernate: 
    insert 
    into
        member
        (id, name, team_id) 
    values
        (null, ?, ?)
Hibernate: 
    insert 
    into
        member
        (id, name, team_id) 
    values
        (null, ?, ?)

자식관계를 끊어냈음에도 불구하고 딜리트쿼리가 나가지 않았다.

이때 orphanRemoval = true 옵션을 연관관계에 적용하면 딜리트 쿼리가 나간다.

 

// JpaLearningTest.java
@DisplayName("orphanRemoval = true - 부모 엔티티(Team)에서 자식 엔티티(Member)를 제거하는 경우")
@Test
void orphanRemoval_True_InCaseOfMemberRemovalFromTeam() {
    // given
    Member member1 = new Member();
    Member member2 = new Member();

    Team team = new Team();

    team.addMember(member1);
    team.addMember(member2);

    teamRepository.save(team);

    // when
    team.getMembers().remove(0);

    // then
    List<Team> teams = teamRepository.findAll();
    List<Member> members = memberRepository.findAll();

    assertThat(teams).hasSize(1);
    assertThat(members).hasSize(1);
}
// DML
Hibernate: 
    insert 
    into
        team
        (id, name) 
    values
        (null, ?)
Hibernate: 
    insert 
    into
        member
        (id, name, team_id) 
    values
        (null, ?, ?)
Hibernate: 
    insert 
    into
        member
        (id, name, team_id) 
    values
        (null, ?, ?)

Hibernate: 
    select
        team0_.id as id1_1_,
        team0_.name as name2_1_ 
    from
        team team0_

Hibernate: 
    delete 
    from
        member 
    where
        id=?

 

이렇게 딜리트쿼리가 나간다.

 

 

출처 : JPA CascadeType.REMOVE vs orphanRemoval = true (techcourse.co.kr)