-
#JPA-15 속성 전이: CASCADEJPA 2021. 2. 19. 17:55
[출처] 인프런 김영한 강사님 -자바 ORM 표준 JPA 프로그래밍 기본
속성 전이: CASCADE
(즉시,지연 로딩, 연관관계 설정과 전혀 관계가 없다. )
• 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때
• 예: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장.속성 전이: 저장
Parent class
package hello.jpa; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity public class Parent { @Id @GeneratedValue private Long id; private String name; @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) private List<Child> childList = new ArrayList<>(); //편의 메서드 public void addChild(Child child){ childList.add(child); child.setParent(this); } 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; } }
Child class
package hello.jpa; import javax.persistence.*; @Entity 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 Class
Parent parent = new Parent(); Child child1 = new Child(); Child child2 = new Child(); parent.addChild(child1); parent.addChild(child2); em.persist(parent); // em.persist(child1); // em.persist(child2); //이건 귀찮다 parent 중심으로 개발을 하고 싶은데 parent를 persit할때 child를 자동으로 persit하고 싶어 //이때 쓰는 것이 casecade tx.commit();
casecade를 하지 않으면 em.persist를 주석 한부분처럼 두번 더써야하는데 casecade 함으로서 1번이면 해결된다.
simple하게 parent를 persist할때 연관된 애들까지 persist를 할꺼야!!
@OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
속성 전이: CASCADE - 주의!
• 속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없음• 엔티티를 속화할 때 연관된 엔티티도 함께 속화하는 편리함 을 제공할 뿐 그 이상 그 이하도 아니다.
CASCADE의 종류
• ALL: 모두 적용 (life cycle을 다 맞춰야해 하면 ALL)
• PERSIST: 영속 (저장할때만 life cycle맞추고 나머지는 따로 돌꺼야 하면 PERSIST)
• REMOVE: 삭제
• MERGE: 병합
• REFRESH: REFRESH
• DETACH: DETACH
CASCADE를 언제쓸거야?
• 일대다에는 다 casecade를 하느냐?? ->아니다
• 하나의 부모가 자식들을 관리할때는 의미가 있다. (소유자가 하나일 때), 단일 entity에 완전히 종속적일때
parent와 child의 life cycle이 완전히 똑같을때(등록하거나 삭제할때 가 유사할때)
(EX O) 게시판 첨부파일 , 첨부파일 데이터나 경로 첨부파일 경로는 한 게시판에서만 관리하기 때문이다.)
(EX X) 파일을 여러군데서 다른 ENTITY에서 관리할 경우에는 쓰면안됨
ex) Parent말고 Member가 child를 알고있다? 이경우에 사용 x)
고아 객체
• 고아 객체 제거: 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제
• orphanRemoval = true
• Parent parent1 = em.find(Parent.class, id); //찾음
parent1.getChildren().remove(0);
//자식 엔티티를 컬렉션에서 제거(연관관계 제거)
• DELETE FROM CHILD WHERE ID = ? //delete 쿼리가 나간다.
Parent parent = new Parent(); Child child1 = new Child(); Child child2 = new Child(); parent.addChild(child1); parent.addChild(child2); em.persist(parent); em.flush(); em.clear(); Parent findParent = em.find(Parent.class, parent.getId()); findParent.getChildList().remove(0); tx.commit();
고아 객체 - 주의
• 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
• 참조하는 곳이 하나일 때 사용해야함!
• 특정 엔티티가 개인 소유할 때 사용
• @OneToOne, @OneToMany만 가능
• 참고: 개념적으로 부모를 제거하면 자식은 고아가 된다. 따라서 고아 객체 제거 기능을 활성화 하면,
부모를 제거할 때 자식도 함께 제거된다.
이것은 CascadeType.REMOVE처럼 동작한다.
casecade를 지운 상태 JpaMain class
Parent parent = new Parent(); Child child1 = new Child(); Child child2 = new Child(); parent.addChild(child1); parent.addChild(child2); em.persist(parent); em.persist(child1); em.persist(child2); em.flush(); em.clear(); Parent findParent = em.find(Parent.class, parent.getId()); em.remove(findParent); //parent를 지우면? tx.commit();
em.remove로 parent를 지우게 되면 parent가 지워진다. 그러면 orphanRemoval 입장에서는 childList까지 다 지우게됨.
ALL 애를지우면 당연히 delete가 전파되기 때문에 child 및 parent를 다 지운다.
속성 전이 + 고아 객체, 생명주기
CascadeType.ALL + orphanRemovel=true
• 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거
• 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있음
(자식을 remove하지 않아도 자식이 지워진다. )
-> 생명주기를 parent는 jpa를 통해서 관리되지만 child의 생명주기는 parent가 관리한다.
• 도메인 주도 설계(DDD)의 Aggregate Root개념을 구현할 때 유용
(repository는 Aggregate Root만 contact하고 나머지는 repository를 만들지 않는 것 이 더낫다. Aggregate Root 관리하는 밑에 애들은 repository를 따로 만들지않고 Aggregate Root 통해서 생명주기를 관리한다.)
실전 예제 - 5.연관관계 관리
글로벌 페치 전략 설정
• 모든 연관관계를 지연 로딩으로• @ManyToOne, @OneToOne은 기본이 즉시 로딩이므로 지연 로딩으로 변경
속성 전이 설정• Order -> Delivery를 속성 전이 ALL 설정
• Order -> OrderItem을 속성 전이 ALL 설정
'JPA' 카테고리의 다른 글
#JPA-17 JPA가 지원하는 다양한 쿼리 방법 (0) 2021.02.23 #JPA-16 값 타입 (0) 2021.02.22 #JPA-14 즉시 로딩과 지연 로딩 (0) 2021.02.19 #JPA-13 프록시 (0) 2021.02.19 #JPA-12 상속관계 매핑 (0) 2021.02.19