Skip to main content Link Menu Expand (external link) Document Search Copy Copied

JPA 프록시와 영속성 전이

Table of contents

  1. 프록시
    1. JPA의 데이터베이스 접근 메커니즘 (쿼리 실행 조건)
  2. 영속성 전이

프록시


JPA의 데이터베이스 접근 메커니즘 (쿼리 실행 조건)


JPA가 데이터베이스에 있는 테이블에 접근하는 메커니즘을 간단하게 설명해보겠다.

객체 간(데이터베이스 상 테이블 간) 연관 관계가 되어 있을 때,

연관되어 있는 객체의 정보를 사용하지 않는 이상 연관된 객체(테이블)에 대해서는 쿼리를 실행시키지 않고 임시 객체 상태로서 보관하고 있고, 이 가짜 객체 상태를 프록시라고 한다.

프록시가 사용자의 요청에 의해서, 진짜 객체 데이터로 채워지면 엔티티 객체로 완전히 바뀌는 것이 아니기 때문에 타입 체크시 == 이 아닌 instance of 를 사용해야 한다!!


예를 들어, Member 테이블과 Team 테이블이 서로 연관되어 있고, Member 클래스 안에 team 이라는 변수명으로 Team과 매핑되어 있을 때,

연관되어 있는 다른 객체를 프록시로 가져오고 싶다면 @XToOne(fetch = FetchType.LAZY) 참조된 객체에 어노테이션 설정을 추가해주어야 한다.

XToMany 는 디폴트 설정이 LAZY라서 명시하지 않아도 된다.

이를 지연로딩 설정이라고 하고, 지연 로딩 설정을 하게 되면

MemberTeam과 연관되어있지 않은 변수를 사용할때는, 데이터베이스에서 Member 테이블에만 접근을 하고,

Member 가 가진 team 객체의 외래키가 아닌 데이터를 사용하려고 할때, 그제서야 데이터베이스의 Team 테이블에 접근하고 프록시에 데이터를 채운다.

쿼리문 실행을 최소화 시키려는 시스템이라고 볼 수 있다.


영속성 전이


  • 연관된 객체를 영속성 컨텍스트에 저장하고 싶을 때 사용
	  // 구문
        Child child1 = new Child();
        child1.setChildName("son");
        child1.setChileAge("1");

        Child child2 = new Child();
        child2.setChildName("daughter");
        child2.setChileAge("2");

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

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

        em.flush();
        em.clear();
        
        //Child 클래스의 연관관계 메서드
        
        public void addParent(Parent parent) {
        this.parent = parent;
        parent.getChilds().add(this);
    	}

위와 같은 구문이 있다고 가정해보자.

영속성 전이 설정(cascade = CascadeType.ALL) 이 되어 있지 않으면 에러를 발생시킨다.

왜냐하면, child1, child2 객체만 영속성 컨텍스트로 persist 되었고 parent 는 persist 되지 않았기 때문에,

DB에서 child 관련 쿼리문만 실행되고, 결국엔 parent 테이블 외래키 값이 null이 되면서 에러를 발생시키게 되는 것이다.

따라서, em.persist(parent) 해주던가 영속성 전이 설정((cascade = CascadeType.ALL) )을 해주어야 한다.