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

김동민님의 프로필 이미지
김동민

작성한 질문수

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

벌크 연산

연관관계 주인과 cascade가 상충되는 상황에 대해서

해결된 질문

작성

·

404

·

수정됨

0

제가 알고 있기론 연관관계 주인만 엔티티 수정이 가능하고 아니면 조회만 가능하다고 알고 있습니다.

@OneToMany(mappedBy = "team") 
private List<Member> members = new ArrayList<>();

이 코드에서 team은 member을 조회만 할수 있습니다.

Team team = new Team(); 
team.setName("TeamA"); 
em.persist(team);

Member member = new Member();

//역방향(주인이 아닌 방향)에서 멤버 추가 시도 
team.getMembers().add(member); //실패!

 

그러나 cascade 또는 고아 객체 제거 옵션을 사용하면 부모 엔티티를 통해 자식 엔티티의 생명주기를 컨트롤 할 수 있다고 배웠습니다.

@Entity 
public class Parent { 

    @Id @GeneratedValue 
    private Long id; 

    @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST) 
    List<Child> childList = new ArrayList<>(); 

}
Child child1 = new Child(); 
Child child2 = new Child(); 

Parent parent = new Parent(); 

child1.setParent(parent); //연관관계 추가 
child2.setParent(parent); //연관관계 추가 

parent.getChildList().add(child1); 
parent.getChildList().add(child2); 

//부모 저장, 연관된 자식들 저장 
em.persist(parent);

 

두 개념이 서로 충돌하는것 같은데 어떻게 동작하는 것일까요?

 

답변 1

2

양방향 연관관계에서 연관관계의 주인은 외래키를 관리하고, 아닌 쪽은 조회만 가능합니다.

Parent에서 아무리 child를 add해도 외래키 값은 저장되지 않습니다.

 

영속성 전이(cascade)는 특정 엔티티의 영속성(persist, remove, detach 등등..)을 수정할 때 연관된 엔티티도 같이 수정하겠다는 뜻입니다.

 

@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)

위 코드를 보시면 연관관계 주인은 Child클래스의 parent이고, Parent클래스를 영속화할 때 Child도 같이 영속화 하겠다는 뜻입니다.

 

올려주신 코드를 보면 child1, child2객체(각각 연관관계의 주인입니다.)에 parent를 set해주므로 외래키가 저장되는 것이며, parent객체(영속성 전이)를 영속화할때 child1, child2객체가 모두 영속화되어 결과적으로 DB에는 총 3개의 데이터(parent, child1, child2)가 INSERT됩니다.

 

child1.setParent(parent); //연관관계 추가

child2.setParent(parent); //연관관계 추가

위 코드를 삭제하시면 연관관계의 주인에 연관관계가 세팅되지 않으므로 외래키값은 null로 입력되는 것을 확인할 수 있으실겁니다.

김동민님의 프로필 이미지
김동민
질문자

그렇다면, cascade나 고아 객체 삭제 옵션은 외래키를 설정하는 연관관계 매핑과 무관하게, 단순히 연관된 객체를 영속 상태로 편리하게 바꿔주는 역할을 하는 거군요! 답변 감사합니다!

김동민님의 프로필 이미지
김동민

작성한 질문수

질문하기