ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] 프록시와 연관관계
    Backend/Spring 2022. 8. 25. 17:18

    객체 그래프 탐색

    객체는 객체 그래프로 연관된 객체를 탐색한다. order.getMember()나 member.getOrders()와 같이 가능하다.

    https://miraekwak.tistory.com/125

     

    [Spring] 연관 관계 매핑

    단일 엔티티 매핑 https://miraekwak.tistory.com/124 [Spring] 단일 엔티티 매핑 단일 엔티티 매핑 JPA는 엔티티 객체를 생성할 때, 기본 생성자 (Default Constructor)를 사용한다. @Entity : 영속성 컨텍스트에..

    miraekwak.tistory.com

     

    Entity는 객체가 데이터베이스(RDB)와 매핑되어 있어서 자유롭게 객체를 탐색하는데 제한이 있다. order.getMember()를 하려고 한다면 orders 테이블과 member 테이블의 정보를 모두 가져와야 하는 상태이기 때문이다.

     

    JPA는 프록시객체라는 기술을 사용하여 연관된 객체를 처음부터 데이터베이스에서 조회하지 않고, 실제 사용하는 시점에 조회할 수 있다. order.getMember()를 했을 때 select 쿼리가 실행되도록 해주는 전략으로 그 전까지는 order 객체를 가져왔을 때 member객체는 JPA의 프록시 객체로 매핑되어 있다.

     

     

    프록시 객체

    FetchType에는 LAZY와 EAGER가 존재하는데, LAZY를 사용할 경우 proxy 객체로 일단 매핑된다.

    @Entity
    @Table(name = "member")
    public class Member extends BaseEntity {
    		...
    
        @OneToMany(mappedBy = "member", fetch = FetchType.LAZY)
        private List<Order> orders = new ArrayList<>(); // proxy
    
        ...
    }

     

    특징

    • 프록시 객체는 처음 사용할 때 한번만 초기화 된다.
    • 프록시 객체가 초기화되면, 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다.
    • 초기화는 영속성 컨텍스트의 도움을 받아야 가능하다. 따라서 준영속 상태의 프록시를 초기화하면 LazyInitializationException 예외가 발생한다.

     

    지연로딩(LAZY) & 즉시로딩(EAGER)

    지연로딩

    연관된 엔티티를 실제 사용할 때 조회한다.

    LAZY FETCH

     

    즉시로딩

    엔티티를 조회할 때, 연관된 엔티티를 함께 조회한다.

    EAGER FETCH

     

    영속성 전이(CASCADE)

    특정 엔티티를 영속 상태로 만들 때, 연관된 엔티티도 함께 영속상태로 만들고 싶을 때, 사용한다.

    public enum CascadeType {
        ALL,
        PERSIST,
        MERGE,
        REMOVE,
        REFRESH,
        DETACH;
    
        private CascadeType() {
        }
    }

    CASCADE의 종류

    • ALL : 모두 적용
    • PERSIST : 영속
    • MERGE : 병합
    • REMOVE : 삭제
    • REFRESH : REFRESH
    • DETACH : DETACH

     

    고아객체

    부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능이다.

    @Entity
    @Table(name = "member")
    public class Member extends BaseEntity {
        ...
    
        @OneToMany(mappedBy = "member", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
        private List<Order> orders = new ArrayList<>();
    
    		...
    }
    • orphanRemoval 속성은 default가 false로 false일 경우 고아 상태일 때 DB에서 삭제하지 않겠다는 것으로 DB에서 삭제하기 위해 true로 변경한다.
    @Test
    void orphan() {
        EntityManager entityManager = emf.createEntityManager();
    
        // 회원 조회 -> 회원의 주문 까지 조회
        Member findMember = entityManager.find(Member.class, 1L);
        findMember.getOrders().remove(0); // order를 제거한다. (고아객체)
    
        EntityTransaction transaction = entityManager.getTransaction();
    
        transaction.begin();
        transaction.commit();
    }

     

    댓글

Designed by Tistory.