코드 그라데이션

영속성 전이(CASCADE) 본문

Spring/JPA 공부

영속성 전이(CASCADE)

완벽한 장면 2023. 8. 25. 14:59

영속성 전이(CASCADE)

  • 즉시 로딩, 지연 로딩, 연관관계 매핑과 전혀 관계가 없음.

 

 

영속성 전이: 저장

 

 

영속성 전이: CASCADE - 주의!

 

 

CASCADE의 종류

 


예제

Parent

@Entity
@NoArgsConstructor
public class Parent {

  @Id
  @GeneratedValue
  private Long id;

  private String name;

  @OneToMany(mappedBy = "parent") // 양방향 매핑 완료
  private List<Child> childList = new ArrayList<>();

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List<Child> getChildList() {
    return childList;
  }

  public void setChildList(List<Child> childList) {
    this.childList = childList;
  }

  // 연관관계 편의 메서드 만들기
  public void addChild(Child child) {
    childList.add(child);
    child.setParent(this);
  }

}

 

child

@Entity
@NoArgsConstructor
public class Child {

  @Id
  @GeneratedValue
  private Long id;

  private String name;

  @ManyToOne
  @JoinColumn(name = "parent_id")
  private Parent parent;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Parent getParent() {
    return parent;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
  }
}

 

 

JpaMain

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
      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);

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      e.printStackTrace(); // 하나 찍어봄
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

이렇게 하면 persist가 3번이 된다.

확인

13:33:35.237 [main] DEBUG org.hibernate.SQL - 
// Parent 1번, Child 2번
Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Parent
        */ insert 
        into
            Parent
            (name, id) 
        values
            (?, ?)

Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)

Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)

 

그런데 나는 persist() 3번이 아니라, Parent 중심으로 코드를 짜고 있으므로

Parent가 책임지고 관리를 해줬으면 좋겠다.

(parent가 persist() 될 때 child가 자동으로 persist() 되었으면 좋겠다.)

무작정 

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

이거 두 개 지워버리면 에러 나옴.

 

이 때 쓰는 게 CASCADE !!!

 

Parent에

@OneToMany(mappedBy = "parent",cascade = CascadeType.ALL) // 양방향 매핑 완료, CASCADE옵션 추가
private List<Child> childList = new ArrayList<>();

추가,

JPAMain

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
      Child child1 = new Child();
      Child child2 = new Child();

      Parent parent = new Parent();
      parent.addChild(child1);
      parent.addChild(child2);

      em.persist(parent);
      // CASCADE 옵션 집어넣고 아래 두 개는 지운다.
//      em.persist(child1);
//      em.persist(child2);

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
      e.printStackTrace(); // 하나 찍어봄
    } finally {
      em.close();
    }
    emf.close();
  }
}

이렇게 만들고 실행하면

13:39:19.693 [main] DEBUG org.hibernate.SQL - 

Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Parent
        */ insert 
        into
            Parent
            (name, id) 
        values
            (?, ?)
13:39:19.696 [main] DEBUG org.hibernate.SQL - 

Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)
13:39:19.697 [main] DEBUG org.hibernate.SQL - 

Hibernate: 
    /* insert inflearn.exjpa.jpaExample.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)

똑같이 세 번이 나온다!

오랜만에 H2 가서 확인해보아도 

즉시 로딩, 지연 로딩, 연관관계 매핑 차원이 아니라,

Parent를 persist() 할 때, 얘 밑에 있는 애들도 같이 persist() 를 날려줄거야 하는 게 CASCADE

 


주의할 게 있다.

 

CASCADE 사용 조건

(반드시 지켜야 탈이 안 난다)

 

728x90

'Spring > JPA 공부' 카테고리의 다른 글

실전 예제 - 5. 연관관계 관리  (0) 2023.08.25
고아 객체, 그리고 생명 주기  (0) 2023.08.25
지연 로딩 활용  (0) 2023.08.24
즉시 로딩  (0) 2023.08.24
지연 로딩  (0) 2023.08.24
Comments