2023. 02.07 16:30 복습 시작
이번 시간에는 영속성 전이와 고아 객체에 대해 학습해보겠다.
영속성 전이 : CASCADE
특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 영속성 전이 기능을 사용해야 한다.
JPA는 CASCADE 옵션으로 영속성 전이를 제공한다.
쉽게 말해서 영속성 전이를 사용하면 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장할 수 있다.
예를 들어 일대다 단방향 부모와 자식 연관 관계가 있다고 생각해보자.
코드는 아래와 같다. (부모 : 자식, 1 : N)
@Entity
public class Parent{
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "parent")
private List<Child> children = new ArrayList<Child>();
}
@Entity
public class Child{
@Id @GeneratedValue
private Long id;
@ManyToOne
private Parent parent;
}
만약 부모 1명에 자식 2명을 저장한다면 아래와 같은 코드를 작성해야 한다.
//부모 저장
Parent parent = new Parent();
em.persist(parent);
//1번 자식 저장
Child child1 = new Child();
child1.setParent(parent);
parent.getChildren().add(child1);
em.persist(child1);
//2번 자식 저장
Child child2 = new Child();
child2.setParent(parent);
parent.getChildren().add(child2);
em.persist(child2);
JPA에서 엔티티를 저장할 때 연관된 모든 엔티티를 영속 상태여야 한다.
따라서 부모, 자식 엔티티도 영속 상태로 만들어야 한다.
이럴 때 영속성 전이를 사용하면 부모, 자식 엔티티를 한 번에 영속 상태로 만들 수 있다.
이제 위 Parent 코드에 영속성 전이를 활성화하는 CASCADE 옵션을 적용해보자.
@Entity
public class Parent{
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST) //이 부분을 추가
private List<Child> children = new ArrayList<Child>();
}
부모를 영속화할 때 자식들도 함께 영속화하라고 cascade = CascadeType.PERSIST 옵션을 적용했다.
이제 아래 코드로 한꺼번에 영속 상태로 만들 수 있다.
Child child1 = new Child();
Child child2 = new Child();
Parent parent = new Parent();
child1.setParent(parent);
child2.setParent(parent);
parent.getChildren().add(child1);
parent.getChildren().add(child2);
em.persist(parent); //부모, 자식들 저장
아래는 CASCADE의 종류다.
- ALL : 모두 적용
- PERSIST : 영속
- REMOVE : 삭제
- MERGE : 병합
- REFRESH : REFRESH
- DETACH : DETACH
고아 객체
고아 객체 제거란 부모 엔티티와 연관 관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능이다.
고아 객체 제거 기능을 활용한 코드는 아래와 같다.
@Entity
public class Parent{
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "parent", orphanRemoval = true) //고아 객체 제거 활성화
private List<Child> children = new ArrayList<Child>();
}
고아 객체 기능을 활성화하기 위해 컬렉션에 orphanRemoval = true를 설정했다.
Parent parent1 = em.find(Parent.class, id);
parent1.getChildren().remove(0); //자식 엔티티를 컬렉션에서 제거
컬렉션에서 첫 번째 자식을 제거했다.
고아 객체 제거 옵션으로 인해 컬렉션에서 엔티티를 제거하면 DB의 데이터도 삭제된다.
고아 객체 제거 기능은 영속성 컨텍스트를 플러시 할 때 적용되므로 플러시 시점에 DELETE SQL이 실행된다.
고아 객체 내용을 정리해보자.
- 고아 객체 제거란 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능이다.
- 이 기능은 참조하는 곳이 하나일 때만 사용해야 한다. 즉 특정 엔티티가 개인 소유하는 엔티티에만 이 기능을 적용한다.
- 만약 삭제한 엔티티를 다른 곳에서 사용하면 당연히 문제 발생.
- @OneToOne, @OneToMany만 사용 가능.
- 부모를 제거하면 자식은 고아가 된다. 따라서 이 기능을 쓰면 부모를 제거하면 자식들도 제거된다.
영속성 전이 + 고아 객체, 생명 주기
CascadeType.ALL + orphanRemoval = true를 동시에 사용한다면, 부모 엔티티를 통해 자식의 생명주기를 관리할 수 있다.
참고자료
자바 ORM 표준 JPA 프로그래밍 - 김영한
자바 ORM 표준 JPA 프로그래밍 강의 - https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
2023. 02.07 17:00 복습 및 정리 마무리
댓글