[JPA] 프록시와 연관관계 - 2

2022. 12. 28. 19:49·Spring/JPA
728x90
반응형

4) 영속성 전이 :CASCADE (생각보다 많이 씀) 

 

CASCADE 란? 즉시 로딩 레이지 로딩과 아무 관계도 아니다!

(헷갈릴 수는 있음) 

특정 엔티티를 영속화 시킬 때 연관 엔티티도 함께 영속화 시키는 것을 말한다. 예시를 다음과 같이 보자. 

@Entity
@Data
public class Parent {

    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @OneToMany(mappedBy = "parent")
    private List<Child> children = new ArrayList<>();

    public void addChild(Child child) {

        children.add(child);
        child.setParent(this);

    }
}

@Entity
@Data
public class Child {
    @Id
    @GeneratedValue
    private Long id;
    private String name;

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

//

//

@Test
@DisplayName("CASCADE")
void test1() {

    tx.begin();
    try {

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


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

        // Parent 중심으로 할 것이기 때문에, Child 는 Parent 영속화되면 좀 자동으로 되었으면 좋겠음
        em.persist(parent);
        em.persist(child1);
        em.persist(child2);
        
        tx.commit();
    } catch (Exception e) {
        e.printStackTrace();
        tx.rollback();
    } finally {
        em.close();
    }
    emf.close();
}

 

persist 가 저렇게 점점 복잡해질 수도 있으니, 다음과 같이 해줄 수 있다. 

 

@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)\

 private List<Child> children = new ArrayList<>();

 

로 바꿀 수 있다. 

이제는 저 위에 child persist  들을 하지 않더라도, em.persist(parent) 만 하더라도 child 두개 모두 영속성 컨텍스트에 등록된다. Parent 안에 있는 Child(?) 또 상속관계는 아님. 그런 상황에서 한꺼번에 하는걸 cascade 라고 함. 

 

>>> 영속성 전이는 매핑이랑 아무 상관 없다! 

>>> ALL : PERSIST : REMOVE (ALL: 은 다 맞춰서 라이프 사이클 // Persist : 저장에 대해서만 맞춤, 그 이후로는 안맞춤) 

 

그렇다고 1:N에는 다 걸면 되는거냐?? 그건 ㄴㄴㄴㄴ

만약에 N의 대상이 되는 애들이 그 1만이 관리한다. 그러면 CASCADE 쓰면 좋음. 하지만 그 N 대상을 관리하는 객체들이 여러개, 

 

가령, 

Teacher 라는 엔티티가 생기고, Teacher 가 Child 와 또다른 1:N 관계면 Cascade 안하는게 좋음. 

왜냐면 그러면 알게 모르게 Query 들이 더 생길 수 있기 때문.

 

그냥 문제의 여지가 있는것은 안쓰는게 제~~일 깔끔함. 보통 이렇게 간단한 관계들이 아니라 진짜 개복잡함 엔티티들. 

 

 

5) 고아 객체

 

> 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제. 

다음과 같이 고아 객체 제거를 활성화 시킬 수 있다. 

 

@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)

 private List<Child> children = new ArrayList<>();

 

Parent 는 이 컬렉션을 관리하고 있는데, 이 컬렉션에서 빠지는 Child 객체들은 자동으로 삭제되어 DELETE 쿼리가 나가게 된다. 위에 예시에서 조금 더 연장을 해보자. 

 

            // Parent 중심으로 할 것이기 때문에, Child 는 Parent 영속화되면 좀 자동으로 되었으면 좋겠음
            em.persist(parent);
//            em.persist(child1);
//            em.persist(child2);

            // 그냥 제대로 쿼리 확인하기 위함
            em.flush();
            em.clear();

            Parent parent1 = em.find(Parent.class, parent.getId());
            parent.getChildren().remove(0);

            tx.commit();

이와 같이 연장후 실행할 경우, child 중 하나가 db에서 삭제됨. 

이거 조심해야하지만, 정말 쓰기도 함. 

참조하는 곳이 하나일 때 사용하는 것, 특정 엔티티가 완전히 소유 대상일때만 사용해야 함. Cascade 와 비슷. 

 

orphanRemoval 의 또하나의 특징은, 

자식들을 모두 삭제함. 

(약간 특정 객체들 삭제할 때 사용하기 좋을 듯??) 

>> 가령, 위에서 parent1 을 삭제하면, parent1.getChildren 해서 조회가 가능한 모든 Child 객체들에 대한 DELETE 쿼리가 날라감. 위에서 em.remove(parent1) 을 하면 Parent 객체를 삭제하면서, 조회되는 Child 에 대한 DELETE 쿼리들도 다 날라간다. 

 

 

6) 영속성 전이 + 고아 객체, 생명 주기

 

둘다 All, True 로 각각 켜주게 되면, 부모 엔티티를 통해서 자식의 생명 주기를 완벽히 통제할 수 있다. (다시 한번 말하지만 Parent 로 삼는 객체가 하나일 때만 써야함!! 안그러면 겁나 꼬임) 

 

em.persist(parent);

 

em.remove(parent);

 

>> child 에 대해서는 하나도 제어하지 않았는데 DB에 저장되었다가, 삭제되었다가 함. 

>> Child의 생명주기는 온전히 Parent 가 관리하게 되는 것임. 

>> 이거가 나중에 도메인 주도 설계 (DDD) 의 Aggregate Root  개념 구현할 때 용이함. (아예 모르는 내용) 

>> Repository의 제한적인 생성에 대한 내용임. Child 에 대한 Repo 를 하나도 생성하지 않고, Aggregate Root 가 Child를 관리하는 그런 거임. (즉, Parent 가 이 설계를 주도하는 것) 

 

이상, 연관관계 및 프록시 끝~!~!

728x90
반응형

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

[JPA] JPQL 쿼리  (0) 2022.12.29
[JPA] - 값 타입  (0) 2022.12.29
[JPA] 프록시와 연관관계 정리  (0) 2022.12.26
[JPA] 연관관계 매핑 -2  (0) 2022.12.26
[JPA] - 엔티티 매핑  (1) 2022.12.21
'Spring/JPA' 카테고리의 다른 글
  • [JPA] JPQL 쿼리
  • [JPA] - 값 타입
  • [JPA] 프록시와 연관관계 정리
  • [JPA] 연관관계 매핑 -2
문케이크
문케이크
    반응형
  • 문케이크
    누구나 개발할 수 있다
    문케이크
  • 전체
    오늘
    어제
    • 전체 보기 (122)
      • CS 이론 (13)
        • 운영체제 (8)
        • 네트워크 (2)
        • 알고리즘 (0)
        • Storage (3)
      • Spring (26)
        • Spring 기본 (12)
        • Spring 심화 (0)
        • JPA (11)
        • Spring Security (3)
      • 리액티브 (0)
        • RxJava (0)
      • SW 설계 (14)
        • OOP (0)
        • UML (3)
        • OOAD (0)
        • Design Pattern (11)
      • Java (8)
      • 웹 운영 (17)
        • AWS (15)
        • 운영 구축 (2)
      • Testing (3)
        • Unit (3)
      • Extra (3)
        • API 적용 (1)
      • 인프라 기술 (5)
        • Kubernetes (2)
        • Elasticsearch (3)
      • Logging (7)
        • Spring (5)
        • 인프라 (2)
      • 일상 (2)
        • 음식점 리뷰 (2)
        • Extra (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 문케이크의 블로그
  • 인기 글

  • 태그

    Configuration
    elasticsearch
    SRP
    Design Pattern
    OOP
    단위테스트
    Java
    lombok
    analyzer
    composition
    k8s
    BEAN
    OOAD
    객체지향
    Composite
    decorator
    JPA
    spring container
    lazy loading
    junit
    디자인 패턴
    Setter
    mockito
    spring boot
    김영한
    di
    Spring
    n+1
    GoF
    runtime exception
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
문케이크
[JPA] 프록시와 연관관계 - 2
상단으로

티스토리툴바