alt
Home JPA와 Proxy
Post
Cancel

JPA와 Proxy


Proxy사용 이유

: 엔티티를 실제 사용하는 시점에 DB에서 가져오기 위해 사용한다.

  • e.g ) Team과 Member 클래스가 있다고 가정할 때, 1 : n 연관관계를 갖게 되고, 각 멤버는 해당하는 팀 객체를 ManyToOne으로(FK) 갖는다. 이 때 Member에 대한 정보를 조회하기 위해 Team 정보까지 조회하는 것은 불필요한 오버헤드

    • 해결방안: lazy loading


lazy loading(지연로딩) : 엔티티 실제 사용 시점까지 조회를 지연하기

  • JPA에서는 지연 로딩하이버네이트에 위임한다. DB 조회를 미루기 위해, 조회 발생 시 하이버네이트 내부에서는 EntityManager.getReference() 를 통해 프록시 객체를 반환한다.

    • Client는 이를 참조하게 된다.
    • 프록시 객체는 실제 객체를 상속받으므로(실제 객체의 참조를 보관) 생김새가 같다. Kotlin + Spring에서 클래스를 open해놓아야 하는 것이 이것 때문이다.


프록시 객체의 초기화

  • 프록시 객체는 member.getName() 이처럼 엔티티 실 사용 시점에 DB 조회해 실제 엔티티 객체를 생성한다. 이 때 영속성 컨텍스트에 엔티티 생성을 요청하고, 생성 후에는 프록시가 진짜 엔티티(진짜 데이터)를 참조하게 된다. 따라서, 참조가 바뀌는 과정은 딱 한번 발생한다.
  • 만일 이미 영속성 컨텍스트가 존재하는 경우 DB 조회는 불필요하므로 위에서 proxy 객체를 반환하는 메서드인 em.getReference() 시에도 실제 엔티티 객체를 반환하게 된다.
  • 초기화는 영속성 컨텍스트의 도움을 받아야한다.
    • Transactional과 life cycle을 같게 갖는 영속성 컨텍스트가 끝나고 준 영속 상태로 변하게 되면 LazyInitializationException 발생한다.
  • 프록시로 엔티티 조회 시 PK를 파라미터로 전달하고, 프록시는 이를 보관한다.
    • 이미 갖고 있는 Id값이므로 getId시에 프록시 초기화하지 않음(단, 옵션 설정시 AccessType.PROPERTY)



Reference)

자바 ORM 표준 JPA 프로그래밍

This post is licensed under CC BY 4.0 by the author.