개발/JPA

영속성 전이, 고아 객체

Debin 2022. 3. 2.
반응형

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

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

2023. 02.07 17:00 복습 및 정리 마무리

반응형

댓글