인프런 커뮤니티 질문&답변

jaewkim님의 프로필 이미지
jaewkim

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

영속성 전이(CASCADE)와 고아 객체

orphanRemoval 동작에 관한 질문 드립니다.

작성

·

382

·

수정됨

0

public class Father {  
    @Id  
    private long id;  
    
    @OneToOne(mappedBy = "father", 
		cascade = CascadeType.PERSIST, 
		orphanRemoval = true)  
    private Child child;

    public void removeChild() {
        if (this.child != null) {
            this.child.father = null;
            this.child = null;
        }
    }
}

public class Mother {  
  @Id  
  private long id;  
  
  @OneToOne(mappedBy = "mother", 
	     cascade = CascadeType.PERSIST)  
  private Child child;
}

public class Child {  
  
  @Id  
  private long id;  
  
  @OneToOne  
  @JoinColumn(name = "mother_id")  
  @OnDelete(action = OnDeleteAction.SET_NULL)  
  private Mother mother;  
  
  @OneToOne  
  @JoinColumn(name = "father_id")  
  @OnDelete(action = OnDeleteAction.SET_NULL)  
  private Father father; 
}


#상황

Father Mother
ㅤㅤ└┳┘
ㅤㅤChild

의 형태로 연관관계를 맺고 있습니다.
orphanRemovalFather에만 설정된 상태입니다.
이러한 상태에서, 몇 가지 테스트를 해본 결과입니다.

(1) Father#removeChild() 호출 시 (연관 관계만 제거), Mother가 연관을 가지고 있더라도 Child 엔티티가 삭제됩니다.

(2) Mother 엔티티를 삭제한 후에, Father 엔티티를 삭제하면, Child 엔티티는 삭제됩니다.

(3) Mother 엔티티를 삭제하지 않고, Father 엔티티만 삭제하면, Child 엔티티는 삭제되지 않습니다.

#질문

(1), (2)번의 경우 이해한대로의 동작이나, (3)번 동작이 이해가 가지 않습니다.

직접 연관관계만 끊을 때와 삭제해서 끊어지는 경우가 다르게 동작하는 것인지... 궁금합니다!

답변 1

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. jaewkim님

우선 강의에서 강조드린 것 처럼 orphanRemoval은 그 기능이 만들어진 의도상 개인 소유일 때만 사용하셔야 합니다.

그러니까 Child가 Father와만 연관관계를 가지고 있을 때는 이 기능을 사용하셔도 됩니다. 하지만 지금처럼 Child가 Father의 소유뿐만 아니라 Mother와 동시 소유의 관계이기 때문에 이런 경우에는 사용하시면 안됩니다.

그러면 지금과 같이 다른 곳에서 동시에 소유했을 때 삭제를 어떻게 해야 하는가에 대한 문제가 남게 됩니다.

 

참고로 orphanRemoval의 동작은 다른 엔티티는 관계가 없어야 합니다.

여기서는 Father와 Child관계만 orphanRemoval 이므로 Mother와는 관계없이 작동해야 합니다.

하지만 JPA에서 삭제를 하려고 해도 다른 연관관계가 남아있기 때문에 이 부분을 결정하지 못하고 유지하는 것으로 보입니다.

이 문제가 버그 때문인지 아니면 의도된 것인지는 저도 정확히는 모르겠습니다.

결론적으로 말씀드리면 해당 기술의 의도에 맞게 개인 소유일 때만 사용하는 것을 권장드립니다.

감사합니다.

jaewkim님의 프로필 이미지
jaewkim

작성한 질문수

질문하기