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

lwisekiml님의 프로필 이미지
lwisekiml

작성한 질문수

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

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

cascade와 고아객체 질문있습니다.

작성

·

206

·

수정됨

0

@Entity
@Getter @Setter
public class Parent {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToOne(mappedBy = "parent")
    private Child child;

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

 

@Entity
@Getter @Setter
public class Child {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
}

 

1. Parent와 child코드가 위와 같을 때 아래 코드에서 에러가 발생하는 이유는 양방향 매핑인데 child를 insert하지 않으니 Parent에 있는 child가 없는 것이 되므로 에러가 발생하는 것이 맞나요?

Parent parent = new Parent();
Child child = new Child();

parent.addChild(child);
em.persist(parent);

 

-------------------------------------------------------------------------------

 

2. mappedBy가 양방향 연관관계를 맺어주는 건데 단순히 아래와 같이 Parent에 있는 mappedBy를 없애면 단방향 연관관계로 바뀌는 건가요?

(아래와 같이 단순히 mappedBy만 없앤 것과 child를 없앤것은 똑같이 단방향을 의미하게 되는 건가요?)

 

public class Parent {

    @Id @GeneratedValue
    private Long id;

    private String name;

    // // mappedBy 만 없다면 이것도 child -> Parent 단방향이 되는 건가요? 아니라면 이 코드는 무슨 의미가 되는 코드인가요?
    @OneToOne
    private Child child;

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

 

public class Parent {

    @Id @GeneratedValue
    private Long id;

    private String name;

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

 

-------------------------------------------------------------------------------

@Entity
@Getter @Setter
public class Parent {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToOne(mappedBy = "parent", fetch = FetchType.LAZY)
    private Child child;

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

 

@Entity
@Getter @Setter
public class Child {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Parent parent;

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

 

3. 위의 코드와 같이 Parent, Child에 둘 다 fetch = FetchType.LAZY를 안하면 아래코드 실행시 join이 발생하는데 왜 발생하는 건가요?

(Parent를 조회하는 것이니 Child에 LAZY를 해주어서 child를 조회하지 않게 한다는 것은 이해가 되는데 왜 Parent에도 LAZY를 해주어야 하나요?

Parent의 @OneToOne이 EAGER라고 해도 Parent 조회하는 것만 EAGER이니 Parent에는 LAZY를 안해도 되것 같은데 왜 LAZY를 해주어야 하는지 궁금합니다.)

Parent parent = new Parent();
Child child = new Child();

parent.addChild(child);
em.persist(parent);
em.persist(child);

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

Parent findParent = em.find(Parent.class, parent.getId());

 

-------------------------------------------------------------------------------

 

4. 3번 질문 코드에서 em.find() 때 쿼리를 보면 select parent와 select child를 하는데 select child 쿼리는 왜 나가는 건가요? LAZY로 동작하지 않고 EAGER로 동작하는 것 같은데 왜 그런건가요?

 

-------------------------------------------------------------------------------

 


@Entity
@Getter @Setter
public class Parent {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToOne(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Child child;

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

 

@Entity
@Getter @Setter
public class Child {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Parent parent;

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

 

 5. 강의에서와 같이 리스트인 child를 삭제하려면 findParent.getChildList().remove(0); 과 같이 하는데, @OneToOne의 경우에는 어떻게 하면 되나요?

 

아래와 같이 Parent의 child 값을 null로 만든 뒤에 remove를 하면 delete 쿼리가 나가는데 이렇게 하면 될까요? 혹시 다른 좋은 방법이 있을까요?

Child child1 = findParent.getChild();
findParent.setChild(null);
em.remove(child1);

 

그리고 아래 코드와 같이 하면 삭제가 왜 안되는 건가요?

Parent findParent = em.find(Parent.class, parent.getId());
em.remove(child);

답변 1

0

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

안녕하세요. lwisekiml님

다음 내용들을 보시면 도움이 되실거에요 🙂

cascade와 mappedBy 차이

https://www.inflearn.com/questions/15855

 

OneToOne LAZY 일대일 지연 로딩

https://www.inflearn.com/questions/40670

 

감사합니다.

lwisekiml님의 프로필 이미지
lwisekiml

작성한 질문수

질문하기