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

조현화님의 프로필 이미지

작성한 질문수

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

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

orphanRemoval = false 설정시 질문

작성

·

363

0

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]
여기에 질문 내용을 남겨주세요.

 

안녕하세요 영한님,

해당 부분 공부하다가 이리저리 검색해보다가 질문 남깁니다!

 

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21710&category=questionDetail&tab=community&q=659760

해당 글에서 서포터즈님께서 답변해주신 바로는,

orphanRemoval = false 설정시

findParent.getChildList().remove(0); 를 통하여 부모객체에서 자식리스트의 자식객체를 삭제하면, DB에는 그대로 남아있지만, FK키가 null로 변한다고 답변해주셨는데요.

제가 실제로 테스트 해본 결과에는.. DB에 FK키가 그대로 부모의 PK키를 명시하고 있습니다.

어떤 것이 맞는 것인지 궁금합니다.

 

 

 

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Parent {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "parent",  orphanRemoval = false)
    private List<Child> childList = new ArrayList<>();

    public void addChild(Child child){
        childList.add(child);
        child.setParent(this);
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Child> getChildList() {
        return childList;
    }

    public void setChildList(List<Child> childList) {
        this.childList = childList;
    }
}
@Entity
public class Child {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }
}
package hellojpa;

import javax.persistence.*;


public class JpaMain {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {

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

            Parent parent = new Parent();
            parent.addChild(child1);
            parent.addChild(child2);

            em.persist(parent);
            em.persist(child1);
            em.persist(child2);

            em.flush();
            em.clear();

            Parent findParent = em.find(Parent.class, parent.getId());
            findParent.getChildList().remove(0);
//            em.remove(findParent);



            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
        emf.close();
    }
}

답변 3

1

정리하면, orphanRemoval=false로 하면, 애플리케이션에서 자식 제거 코드를 작성해도, DB에서는 제거되지 않는다. 다만, CASCADE 가 걸려 있다면, orphanRemoval=false이더라도, DB에서 부모와 같이 자식도 제거되는 걸로 이해하면 될까요?

정리하면, orphanRemoval=false로 하면, 애플리케이션에서 자식 제거 코드를 작성해도, DB에서는 제거되지 않는다.

=> 맞습니다.

CASCADE 가 걸려 있다면, orphanRemoval=false이더라도, DB에서 부모와 같이 자식도 제거되는 걸로 이해하면 될까요?

=> 정확히는 CASCADE.REMOVE 가 걸려있고, 부모를 삭제하면 orphanRemoval=false 여도 부모를 삭제할 때 자식을 같이 삭제하게 됩니다. 그냥 자식 엔티티와의 관계를 제거한다면 자식 엔티티는 삭제되지 않습니다.

 

1

안녕하세요. 조현화님, 공식 서포터즈 y2gcoder입니다.

먼저 이해하시는데 혼동을 드려 죄송합니다. 위의 질문의 답변을 제가 달았었는데, 답변이 다소 모호했던 것 같습니다. 위의 답변에서의 전제는 CASCADE가 걸려있는 것을 전제로 했을 때였습니다.

작성해주신 코드에서는 사실 CASCADE 옵션이 걸려있지 않고 orphanremoval=false로 되어있기 때문에, 실제로는 해당 옵션들이 없는 기본값 상태라고 생각합니다. 그런 상황에서는 말씀하신 것처럼 객체에서 연관관계에 있는 객체를 제거한다고 해서 제거된 객체에 영향을 주지는 않을 것 같습니다.

모호한 답변으로 혼동을 드려 다시 한 번 죄송합니다 (_ _)

감사합니다.

0

안녕하세요, 인프런 AI 인턴이에요.

먼저, 제가 이해한 내용에 대해서 말씀드리겠습니다. 해당 질문에 대한 답변을 찾다가 orphanRemoval=false 설정 시에 “findParent.getChildList().remove(0);” 코드를 통해 부모 객체에서 자식 리스트의 자식 객체를 삭제하면, DB에는 그대로 남아있는 것으로 이해되는데 맞나요?

일반적으로 orphanRemoval=false 설정은 부모 객체와 자식 객체 간의 연관관계를 해제했을 때 자식 객체를 삭제하지 않는 설정입니다. 따라서, 부모 객체에서 자식 객체를 삭제하는 코드를 작성하더라도 실제 DB에는 그대로 남아있습니다. orphanRemoval=true로 설정해야 자식 객체를 DB에서도 함께 삭제할 수 있습니다.

강의와는 다소 관련이 없는 내용이기 때문에 정확한 답변을 위해서는 상세한 내용이 필요할 것 같습니다. 추가적인 질문이 있으시면 알려주세요.