쌓고 쌓다

[JPA] 영속성 전이(CASCADE): 저장 본문

프로그래밍/JPA

[JPA] 영속성 전이(CASCADE): 저장

승민아 2023. 8. 17. 17:25

영속성 전이를 사용하면 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장할 수 있다.

 

영속성 전이를 사용하지 않았을때의 로직을 먼저 보자.

 

영속성 전이 사용

Parent

@Entity
@Getter
@Setter
public class Parent {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

cascade 속성에 CascadeType.PERSIST 값을 주면 된다.

 

Child

@Entity
@Getter
@Setter
public class Child {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private Parent parent;
}

 

한번 아래의 로직 수행 결과를 생각해보자.

public void logic() {
    Child child1 = new Child();
    Child child2 = new Child();

    Parent parent = new Parent();
    parent.getChild().add(child1);
    parent.getChild().add(child2);
    em.persist(parent);
}

부모에 자식을 추가하여 엔티티를 저장했다.

영속성 전이를 통해 부모와 자식 모두 정상적으로 저장이 될 것이다.

 

그런데 자식의 외래 키가 NULL이다...?

아니 선생님 외래 키 관리하는 주인을 mapped로 Child쪽에 있으니 당연히 외래 키 추가를 못하는거 아닌가요??

 

그래서 아래의 로직을 수행해보자.

child는 저장 조차 안된다.

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

 

중요한 개념을 발견했다.

영속성 전이는 연관관계를 매핑하는 것과는 전혀 관련이 없다.

그저 연관된 엔티티를 같이 영속화해주는 편리함만 제공해줄 뿐이다.

 

완벽한 코드는 아래와 같다.

public void logic() {
    child1.setParent(parent); // cascade는 persist만해주는거지 연관관계 매핑을 해주는게 아니다. 이거 안해주면 외래키 null이 들어감
    child2.setParent(parent);
    parent.getChild().add(child1);
    parent.getChild().add(child2);
    em.persist(parent);
}

양방향 연관관계를 추가한 다음 영속 상태로 만들자.

 

정상 저장


@JoinColumn을 적지 않아도 될까?

public class Child {
    @ManyToOne
    private Parent parent;
}

@JoinColumn은 외래 키 매핑시 사용한다고 배웠다.

공부하는 책에는 @JoinColumn이 생략되어있다. 어떻게 된것일까.

 

기본적으로 외래 키 매핑 컬럼 이름을 적어주지 않으면 대상 엔티티의 이름과 기본 키 컬럼의 이름을 조합하여 생성한다.

Child 테이블의 외래 키 컬럼인 parent_id를 p_id로 변경하면 아래의 에러가 발생한다.

org.hibernate.exception.SQLGrammarException:
could not execute statement [Unknown column 'parent_id' in 'field list'] [insert into child (parent_id) values (?)]

기본으로 생성하는 엔티티명_기본키명인 'parent_id'를 찾을 수 없다고한다.

그래서 교재의 경우 parent_id로 외래 키 이름을 일치시켜놨기에 @JoinColumn을 적어주지 않은것 같다.

Comments