"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."
www.inflearn.com/course/ORM-JPA-Basic#
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그
www.inflearn.com
영속성 전이 : CASCADE
특정 Entity 를 영속 상태로 만들 때 연관된 Entity 도 함께 영속 상태로 만들고 싶으면 사용하는 옵션, 즉 부모를 저장할 때 자식도 같이 저장하고 싶으면 사용하는 옵션이다.
(부모를 쓸 때 자동으로 자식 까지 같이 persist 해준다.)
아래와 같이 코드를 작성하고 애플리케이션을 실행해보자.
- Parent.java
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "parent")
private Lisrt<Child> childList = new ArrayList<>();
public void addChild(Child child) { // 연관관계 편의 메소드
childList.add(child);
child.setParent(this);
}
// Getter, Setter
}
- Child.java
@Entity
public class Child {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;
private String name;
private String name;
// Getter, Setter
}
- JpaMain.java
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);
그러면 아래와 같이 3번의 persist 로 인해 insert 쿼리가 3번 나가는 것을 볼 수 있다.
- hibernate SQL
Hibernate:
/* insert hellojpa.Parent
*/ insert
into
Parent
(name, id)
values
(?, ?)
Hibernate:
/* insert hellojpa.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
Hibernate:
/* insert hellojpa.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
코드를 위와 같이 작성해야 3가지 객체 모두 영속성 컨텍스트에 담을 수 있다.
그런데 이렇게 작성하기엔 뭔가 귀찮다.(persist 메소드를 굳이 3번씩이나 호출해야 할까?)
현재 비즈니스 로직에서 persist 를 3번 하는게 아니라, 코드를 짤 때 parent 중심으로 코드를 작성하고 싶다면?
즉, parent 가 child 를 관리하면서 parent 를 persist 할 때 child 도 같이 자동으로 persist 되도록 만들고 싶다면 어떻게 해야 할까?
-> 이럴 때 사용하는게 바로 CASCADE 이다.
Parent 클래스(대상 클래스) 에서 cascade 속성을 all 로 설정해주자.
- Parent.java
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private Lisrt<Child> childList = new ArrayList<>();
이후 child 에 대한 persist 호출 2개를 지운 뒤 다시 애플리케이션을 실행해보자.
- JpaMain.java
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);
그러면 아래와 같이 persist 를 3번 호출한 것과 같은 hibernate SQL 을 출력하는 것을 볼 수 있다.
- hibernate SQL
Hibernate:
/* insert hellojpa.Parent
*/ insert
into
Parent
(name, id)
values
(?, ?)
Hibernate:
/* insert hellojpa.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
Hibernate:
/* insert hellojpa.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
* 연관관계 같은거 전혀 상관없고, Parent 를 persist 할 때 밑에 있는 child 데이터들을(List 컬렉션 안에 있는 데이터들) 전부 다 persist 해주는 것을 CASCADE 라고 한다.
주의 사항?
연관관계를 매핑하는 것과는 아무 관련이 없으며, Entity 를 영속화 할 때 연관된 Entity 도 함께 영속화 하는 편리함만을 제공할 뿐이다.
* CASCADE 의 종류?
여러가지 있으나 일단은 ALL 과 PERSIST 만 기억하자
삭제하면 안될 때, 저장만 할 때는 PERSIST(저장할 때만 persist, 나머지는 따로), 아니면 ALL(정말 모든 라이프 사이클을 모두 맞춰야 할 때) 을 쓰면 된다.
* 또 한가지 주의할 점?
CASCADE 를 언제 써야 할까?
- 꼭 일대다 연관관계 라고 다 걸어야 하는 것은 아니다.
- 하나의 부모가 모든 자식들을 관리할 때는 CASCADE 가 의미가 있다.
(쉽게 말해, 게시판, 첨부파일 경로 등... , 첨부 파일의 경로 같은 경우 첨부 파일이 있는 한 게시물에서만 관리한다.)
- 그런데 예를 들어 파일을 여러군데에서 관리하고 있는 경우(다른 Entity 에서도 관리하는 경우) 엔 사용하면 안된다.
- 소유자가 하나일 때는 써도 되나, 다른 Entity 가 child 와 연관관계가 있다면 사용해서는 안된다.
(child 에서 다른 곳으로 나가는 건 상관없으나, 다른 Entity 가 child 를 알게 되면 사용해서는 안된다.)
- 단일 Entity 에 완전히 종속적이면 사용해도 무관하다.
- Parent 와 Child 의 라이프 사이클이 거의 똑같을 때는 쓰면 된다.(단일 소유일 경우)
다음 글에서는 고아 객체에 대해 알아보자.
'JPA' 카테고리의 다른 글
실전예제 5 - 프록시 및 연관관계 (0) | 2020.10.17 |
---|---|
영속성 전이(CASCADE) 와 고아 객체 - 2 (0) | 2020.10.17 |
프록시 객체와 지연 로딩, 즉시 로딩 - 2 (0) | 2020.10.16 |
프록시 객체와 지연 로딩, 즉시 로딩 - 1 (0) | 2020.10.16 |
프록시와 연관관계 매핑 - 3 (0) | 2020.10.16 |