TIL 2023-11-20 CascadeType.REMOVE orphanRemoval = true 차이

2023. 11. 20. 22:08TIL
목차
  1. 간단 요약
  2. 고아 객체
  3. CascadeType.REMOVE
  4. orphanRemoval = true

간단 요약

CascadeType.REMOVE와 orphanRemoval은 부모 객체를 지우면 자식 객체도 지운다.

 

차이점은 부모 객체와 자식의 연관관계를 지우면

CacadeType.REMOVE는 자식을 삭제하지 않고

orphanRemoval은 자식을 삭제한다.


고아 객체

부모 엔티티와 연관 관계가 끊어진 객체를 의미한다.

  • 부모 객체를 지우면 모든 자식 객체들은 고아 객체가 된다.
  • 부모 객체가 자식 객체와의 연관관계를 삭제하면, 해당 자식 객체는 고아 객체가 된다.

 

 

CascadeType.REMOVE

  • 부모 객체를 지우면 자식 객체도 지운다.
  • 부모 객체가 자식 객체를 지웠을 때, 자식 객체는 삭제되지 않고 DB에 남아 있는다.

부모 객체 클래스를 만들고


      
@Entity
@Getter
@Setter
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
private List<Child> childs;
}

 

자식 객체 클래스도 만들었다.


      
@Entity
@Getter
@Setter
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column
String name;
@ManyToOne
@JoinColumn(name = "parent_id")
Parent parent;
}

 

테스트 코드를 짜주고 기본적인 부모 자식 세팅을 해주었다.


      
@Test
@Transactional
@Rollback(value = false)
void init() {
List<Parent> parentList = new ArrayList<>();
Parent parent1 = new Parent();
Parent parent2 = new Parent();
parent1.setName("부모 1");
parent2.setName("부모 2");
parentList.add(parent1);
parentList.add(parent2);
parentRepository.saveAll(parentList);
List<Child> childList = new ArrayList<>();
Child child1 = new Child();
Child child2 = new Child();
Child child3 = new Child();
Child child4 = new Child();
child1.setName("부모 1의 자식 1");
child2.setName("부모 1의 자식 2");
child3.setName("부모 2의 자식 1");
child4.setName("부모 2의 자식 2");
child1.setParent(parent1);
child2.setParent(parent1);
child3.setParent(parent2);
child4.setParent(parent2);
childList.add(child1);
childList.add(child2);
childList.add(child3);
childList.add(child4);
childRepository.saveAll(childList);
}

 

 

밑에와 같은 테스트 코드를 짰다.

 


      
@Test
@Transactional
@Rollback(value = false)
void cascadeRemoveTest() {
// 부모 객체 삭제 테스트
Parent parent1 = parentRepository.findByName("부모 1");
parentRepository.delete(parent1);
// 부모 객체와 자식 연관 관계 제거 테스트
Parent parent2 = parentRepository.findByName("부모 2");
List<Child> childList = new ArrayList<>(parent2.getChilds());
for (Child child : childList) {
parent2.getChilds().remove(child);
}
System.out.println("부모 2의 자식 수: "+parent2.getChilds().size());
}

parent1에서는 부모 1을 삭제 할 것이고

 

parent2에서는 자식 2와 연관 관계를 제거 할 것이다.

 

실행 전
실행 후


      
Hibernate:
/* <criteria> */ select
p1_0.id,
p1_0.name
from
parent p1_0
where
p1_0.name=?
Hibernate:
select
c1_0.parent_id,
c1_0.id,
c1_0.name
from
child c1_0
where
c1_0.parent_id=?
Hibernate:
/* delete for com.study.orphan.entity.Child */delete
from
child
where
id=?
Hibernate:
/* delete for com.study.orphan.entity.Child */delete
from
child
where
id=?
Hibernate:
/* delete for com.study.orphan.entity.Parent */delete
from
parent
where
id=?
Hibernate:
/* <criteria> */ select
p1_0.id,
p1_0.name
from
parent p1_0
where
p1_0.name=?
Hibernate:
select
c1_0.parent_id,
c1_0.id,
c1_0.name
from
child c1_0
where
c1_0.parent_id=?

 

 

hibernate에서 Delete 문을 한번만 날렸다. 부모 1만 자식 객체를 지웠다.

 

부모 2의 자식 리스트를 sout으로 테스트를 했을 때

 

부모 2는 자식 리스트에서 자식 1, 2를 지운 것을 확인 할 수 있다.

근데 자식들은 이 사실을 모른다ㅠㅠ

호적을 팠는데... 자식은 모르는 상황...

 

사실 객체 지향적인 관점에서 보면 당연한 것이다.

 

orphanRemoval = true

부모 엔티티 수정


      
@Entity
@Getter
@Setter
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> childs;
}

 

부모 객체에서 수행되는 작업이 자식객체에도 반영이 될 수 있게 Cascade를 넣어줬다.

 

기존 테이블 Drop하고 다시 하면 된다.

 


      
Hibernate:
/* <criteria> */ select
p1_0.id,
p1_0.name
from
parent p1_0
where
p1_0.name=?
Hibernate:
select
c1_0.parent_id,
c1_0.id,
c1_0.name
from
child c1_0
where
c1_0.parent_id=?
Hibernate:
/* delete for com.study.orphan.entity.Child */delete
from
child
where
id=?
Hibernate:
/* delete for com.study.orphan.entity.Child */delete
from
child
where
id=?
Hibernate:
/* delete for com.study.orphan.entity.Parent */delete
from
parent
where
id=?
Hibernate:
/* <criteria> */ select
p1_0.id,
p1_0.name
from
parent p1_0
where
p1_0.name=?
Hibernate:
select
c1_0.parent_id,
c1_0.id,
c1_0.name
from
child c1_0
where
c1_0.parent_id=?
부모 2의 자식 수: 0
Hibernate:
/* delete for com.study.orphan.entity.Child */delete
from
child
where
id=?
Hibernate:
/* delete for com.study.orphan.entity.Child */delete
from
child
where
id=?

 

테스트에 트랜잭션 환경이 설정되어 있어

sout 이후 끝날 때 부모 객체와 연이 끊어진 자식 객체를 삭제 한 모습을 볼 수 있다.

연이 끊어진 자식들은 다 지워진 모습
부모 2만 살아남았다

 

저작자표시 (새창열림)

'TIL' 카테고리의 다른 글

TIL 2023-11-22 gradle 외부 라이브러리 jar 적용 오류  (0) 2023.11.22
TIL 2023-11-21 PUT과 PATCH의 차이  (0) 2023.11.21
TIL 2023-11-17 Entity 연관 관계 정리!  (0) 2023.11.17
TIL 2023-11-16 RestTemplate 짧은 설명  (1) 2023.11.16
TIL 2023-11-15 JWT 검증 과정에서 일어나는 문제 해결 과정  (1) 2023.11.15
  1. 간단 요약
  2. 고아 객체
  3. CascadeType.REMOVE
  4. orphanRemoval = true
'TIL' 카테고리의 다른 글
  • TIL 2023-11-22 gradle 외부 라이브러리 jar 적용 오류
  • TIL 2023-11-21 PUT과 PATCH의 차이
  • TIL 2023-11-17 Entity 연관 관계 정리!
  • TIL 2023-11-16 RestTemplate 짧은 설명
wonow_
wonow_
꾸준히 성장하는 개발자 WONOW 입니다. 🤗
wonow_
wonow_
wonow_
전체
오늘
어제
  • 분류 전체보기
    • Language
      • JAVA
    • TIL
    • 코딩테스트
      • 프로그래머스
      • 백준
    • 프로젝트
      • JAVA
      • Spring
    • 기타
    • ERROR
      • Spring
    • CS
      • 알고리즘
      • DB
      • Kafka
    • 잡담
    • 활동
      • 척척박사

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 공부열심히하자
  • 문자열 붙여서 출력하기
  • 홀짝 구분하기
  • 문자열 돌리기
  • 나는바봉가봉가
  • 티스토리 꾸미기
  • 오블완
  • 프로그래머스
  • 티스토리챌린지

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.1
wonow_
TIL 2023-11-20 CascadeType.REMOVE orphanRemoval = true 차이
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.