ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] Cascade관계에서 추가로 활용하면 좋을 옵션 orphanRemoval
    Spring 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)

    댓글

Designed by Tistory.