Cascade, orphanRemoval 총정리

이수찬·2023년 4월 29일
0
  1. entity 설계

  1. Cascade, orphanRemoval에 따른 쿼리 생성

2-1. Cascade.ALL

  Member2 member2 = member2Repository.findById(rq.getMemberId())
          .orElse(null);

  member2Repository.delete(member2);
  • item 조회 쿼리
  • item 삭제 쿼리
  • member2 삭제 쿼리

2-2. Cascade.ALL + orphanRemoval = true

 Member2 member2 = member2Repository.findById(rq.getMemberId())
          .orElse(null);

  member2Repository.delete(member2);
  • item 조회 쿼리
  • item 삭제 쿼리
  • member2 삭제 쿼리

2-3. CascadeType.PERSIST

Member2 member2 = member2Repository.findById(rq.getMemberId())
        .orElse(null);

member2Repository.delete(member2);
  • item을 조회하지 않고 member2 삭제하려함
  • 아래의 에러 발생
Cannot delete or update a parent row: a foreign key constraint fails (`commerce`.`item`, CONSTRAINT `FKc66jsgb245jkqodj5oi4hewcl` FOREIGN KEY (`member2_id`) REFERENCES `member2` (`id`))

-> member2가 item을 생성하였기에, item에 member테이블의 외래키가 존재한는데,
item을 먼저 조회해서 삭제하지 않고, member2를 먼저 삭제하기에 데이터 정합성이 깨져 에러가 발생한다.

Member2 member2 = member2Repository.findById(rq.getMemberId())
        .orElse(null);

List<Item> itemList = member2.getItemList();

member2Repository.delete(member2);

위와 같이 item조회 쿼리를 날려도 item을 조회할 뿐 삭제하지는 않아 같은 에러가 발생한다.

2-4. CascadeType.PERSIST + orphanRemoval = true

Member2 member2 = member2Repository.findById(rq.getMemberId())
        .orElse(null);

member2Repository.delete(member2);
  • item 조회 쿼리
  • item이 조회되어 영속성 컨텍스트 안에 들어옴
  • item 삭제쿼리
  • member2 삭제 쿼리

2-5. CascadeType.REMOVE

Member2 member2 = member2Repository.findById(rq.getMemberId())
        .orElse(null);

member2Repository.delete(member2);
  • item 조회 쿼리
  • item이 조회되어 영속성 컨텍스트 안에 들어옴
  • item 삭제 쿼리
  • member2 삭제 쿼리

2-6. CascadeType.REMOVE + orphanRemoval = true

Member2 member2 = member2Repository.findById(rq.getMemberId())
        .orElse(null);

member2Repository.delete(member2);
  • item 조회 쿼리
  • item이 조회되어 영속성 컨텍스트 안에 들어옴
  • item 삭제 쿼리
  • member2 삭제 쿼리
  1. CascadeType.REMOVE + orphanRemoval = true를 같이 써야 하는 이유
  • CascadeType.REMOVE의 경우 관계가 끊어진 것을 제거로 보지 않기에 자식 클래스에는 값이 null 값으로 대체된다.

  • orphanRemoval = true?
    CascadeType.REMOVE와 동일하게 parent entity가 삭제되면, 자식 엔티티도 같이 삭제되지만, 관계가 끊어진 child를 자동으로 제거한다. (child 테이블의 row를 제거한다)

3-1. CascadeType.REMOVE + orphanRemoval = true 사용 조건

  • child를 관리하는 parent테이블이 오직 한개 존재하는 경우 사용 가능(다른 엔티티가 child를 알고있는 경우 사용 불가능)

  • child가 다른 엔티티를 알고있는 경우는 사용 가능.
    즉, 고아객체는 참조하는 곳이 하나일 때만 사용 가능하다
    (특정 엔티티가 특정 엔티티의 개인 소유일 때 사용 가능)
    -> 부모 엔티티를 통해서 자식의 생명주기가 관리가능하다는 의미입니다.

0개의 댓글