Home Cascade
Post
Cancel

Cascade

Cascade란 영속성 전이를 말한다. Default Casacde는 아무것도 작성되지 않은 상태이고, PERSIST, MERGE, DETACH, REMOVE, REFRESH, ALL을 제공한다.

PERSIST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
@Transactional
void cascadeTest(){

    Member member = new Member();
    member.setName("A");

    memberRepository.save(member);

    Team team = new team();
    team.setName("ATeam");

    teamRepository.save(team);

    member.setTeam(team); // 연관관계 
    memberRepository.save(member); 

    team.getMembers().add(member);
    teamRepository.save(team);
}
  • Cascade를 하지 않는다면 save를 각각 2번씩 수행 해야한다.
  • member을 save하지 않으면 영속 상태가 되지 않아 member과 team의 관계를 맺을 때 에러가 발생한다. (entity의 relation reference가 DB에 저장 되지 않고 자바 객체이기 때문)
  • cascade를 사용하면 조금 더 깔끔한 코드를 작성할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
      @Entity
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class Member {
    
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
        
          private String name;
    
          private Long age; 
        
          @ManyToOne(cascade = CascadeType.PERSIST)    //추가
          @ToString.Exclude
          private Team team;
      }
    
    • member이라는 entity가 persist될 때 Team도 persist시키는 옵션이다.
  • cascade를 해주는 것으로 test코드는 아래와 같이 작성할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      @Test
      @Transactional
      void cascadeTest(){
    
          Member member = new Member();
          member.setName("A");
    
          Team team = new Team();
          team.setName("ATeam");
    
          member.setTeam(team);
          memberRepository.save(team);
      }
    

MERGE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Test
@Transactional
void cascadeTest(){
    Member member = new Member();
    member.setName("A");

    memberRepository.save(member);

    Team team = new team();
    team.setName("ATeam");

    teamRepository.save(team);

    member.setTeam(team); // 연관관계 
    memberRepository.save(member); 

    team.getMembers().add(member);
    teamRepository.save(team);

    Member member = memberRepository.findById(1L).get();
    member.getTeam().setName("BTeam");
    memberRepository.save(member);
}
  • 영속성 전이를 PERSIST만 설정했기 때문에 변경사항에 대한 전이는 이루어 지지않는다.
  • @ManyToOne(cascade = {CascadeType.PERISIT, CascadeType.MERGE})

orphanRemoval

  • CASACDE.REMOVE와 유사한 느낌
  • CASACDE.REMOVE는 상위 객체가 remove가 수행하면 포함하고 있는 객체의 영속성 이벤트를 전파해서 하위 entity까지 remove시켜주는 옵션이다.
    • CascadeType.Remove 는 참조를 변경시켜 무결성 오류를 안나게 할 뿐, 그 데이터는 남겨두게 된다.
  • orphan removal옵션은 하위 entity를 setter를 통해 null을 넣어주면 db에서도 삭제해주는 옵션이다.
    • null로 설정된 값을 DB에서 삭제하지 않으려면 cascade.remove를 사용해야한다.
    • 두 엔티티의 관계를 끊을 때, 테이블의 데이터가 계속 남아있기를 바란다면, CascadeType.Remove 만 쓰는 것이고, 테이블의 해당 데이터까지 삭제를 바란다면 orPhanRemoval = true 를 사용하는 것이다.
1
@OneToMany(orphanRemoval = true)

soft Delete

  • 상용 DB에서 delete를 query를 사용하는 경우는 거의 없다.
  • 특정 flag를 이용해 지워진 표시만 남긴다.
    • private boolean deleted;
  • Flag가 true라면 출력 Query에서 조회 되어서는 안된다. 따라서 repository에 QueryMethod를 작성해서 사용해야 한다.

    1
    2
    3
    4
    5
    
      public interface MemberRepository extends JpaRepository<Member, Long> {
            
          List<Member> findAllByDeletedFalse();
          List<Member> findByIdDeletedFalse();
      }
    
  • 하지만 이렇게 모든 method를 작성할 수 없고, 실수로 삭제된 데이터가 노출 되는 상황이 발생할 수 있다. 직접 QueryMethod작성하는 대신 @Where를 사용해 처리할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
      @Entity
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @Where(clause = "deleted = false")       //추가
      public class Member {
    
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
        
          private String name;
        
          private Long age;
        
          private boolean deleted;
        
      }
    
    • Where로 처리하면 해당 조건을 항상 체크한다.
This post is licensed under CC BY 4.0 by the author.