본문 바로가기
  • 개발공부 및 일상적인 내용을 작성하는 블로그 입니다.
JPA

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

by 방구석 취준생 2020. 10. 17.

"인프런 - 자바 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 의 라이프 사이클이 거의 똑같을 때는 쓰면 된다.(단일 소유일 경우)

 

 

 

다음 글에서는 고아 객체에 대해 알아보자.