Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 커밋 되돌리기
- Git
- DTO
- 데커
- BindingResult
- JPA
- 무한정 대기
- 쉘 스크립트
- compgen
- @Autowired
- 편향된 지수
- application layer
- @SubscribeMapping
- 프로그래머스
- 런타임 상수
- 은행원알고리즘
- m:n
- 쿠키
- JDBC
- 알고리즘
- 영속화
- 컴파일 타임 상수
- intelij spring config
- 리눅스
- 백준
- 기본키 전략
- spring
- allocationSize
- API
- 파이썬
Archives
- 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://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 |