일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 티스토리챌린지
- JDBC
- 프로그래머스
- 리눅스
- m:n
- 알고리즘
- Git
- 오블완
- BindingResult
- JPA
- @Autowired
- API
- 기본키 전략
- 쉘 스크립트
- mysql
- allocationSize
- 커밋 되돌리기
- 쿠키
- compgen
- 백준
- 런타임 상수
- 편향된 지수
- 파이썬
- 메모리 구조
- DTO
- 컴파일 타임 상수
- application layer
- @SubscribeMapping
- spring
- intelij spring config
- Today
- Total
둘셋 개발!
[JPA] orphanRemoval 옵션 적용 버그 본문
intro.
jpa를 공부하다가 orphanRemoval 옵션이 제대로 동작하지 않았다.
orphanRemoval 옵션을 true로 하면 고아객체 발생 시 해당 고아객체는 삭제되어야 하는데 삭제가 안된 것이다.
클래스 구성
클래스로는 Parent와 Child가 있고,
Parent : Child는 1: N의 관계를 가지고 있다.
Parent.class
@Entity
public class Parent {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "parent", orphanRemoval = true) // 옵션 적용
private List<Child> childList = new ArrayList<>();
public void addChild(Child child) {
childList.add(child);
child.setParent(this);
}
public List<Child> getChildList() {
return childList;
}
// ... set, get
}
@Entity
public class Child {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent = new Parent();
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
// set, get, ...
}
test 코드
tx.begin();
Parent parent = new Parent();
Child child1 = new Child();
parent.addChild(child1);
Child child2 = new Child();
parent.addChild(child2);
em.persist(parent);
em.persist(child1);
em.persist(child2);
em.flush();
em.clear();
System.out.println("--------------------");
// child2를 자식에서 제외
Parent findParent = em.find(Parent.class, parent.getId());
List<Child> childList = findParent.getChildList();
childList.remove(1); // child2와 참조를 끊음!
tx.commit();
결과
delete문도 나가지 않았고, db에도 child2가 남아있었다.

고아 객체가 되는 조건은 1) 부모 객체가 삭제됨 2) 부모객체의 자식컬랙션에서 제외됨이다.
이는 2번에 해당하고 고아객체가 되어 자동으로 삭제하겠금(orphanRemoval=true) 설정했는데, 삭제가 안된 것이다.
그래서 구글링 해본 결과 버그라고 나왔다.
만약 자식컬랜션에서 제외됐을 경우 자동으로 삭제하기를 원한다면 cascade 옵션과 같이 사용해야 한다.
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL,orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST,orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
그럼 실무에 적용할 때는 어떻게?
(김영한님 커뮤니티의 답변을 바탕으로 작성)
보통 orphanRemoval을 단독으로 사용하는 경우는 드물고,
부모객체가 자식객체를 관리하는 경우에는 orphanRemoval와 CascadeType.PERSIST를 같이 사용하기 때문에 괜찮다고 한다.
ref.
https://velog.io/@byeongju/orphanRemoval%EC%9D%B4-%EB%8F%99%EC%9E%91%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4%EB%A9%B4
https://www.inflearn.com/questions/137740/orphanremoval%EA%B3%BC-cascade%EC%9D%98-%EA%B4%80%EA%B3%84
'JPA' 카테고리의 다른 글
[JPA] 복합키 중 autoIncrement키가 있다면? (0) | 2024.08.17 |
---|---|
[JPA] 일대다 양방향에서 '다'엔티티에 @JoinColumn을 생략하면 안되는 이유 (0) | 2023.09.22 |
[JPA] 다대일에서 update쿼리가 잘못 나갈 수 있다..! (0) | 2023.09.22 |
[JPA] Primary Key 자동 생성 전략 (0) | 2023.09.15 |
[JPA 기본편] Jpa 구동방식 (0) | 2022.03.26 |