프록시란?
JPA 구현체들은 연관된 객체들 처음부터 데이터베이스에서 조회하는 것이 아니라, 실제 사용하는 시점에 데이터베이스에서 조회할 수 있다. 이와 관련 된 기술이 프록시 인데, 이 프록시를 통해서 즉시로딩 ( EAGER ) 과 지연로딩 ( LAZY ) 을 할 수 있다.
JPA 표준 명세는 지연 로딩 구현방법을 JPA 구현체에 위임했다. 하이버네이트는 지연 로딩을 지원하기 위해 프록시를 사용하는 방법과 바이트코드를 수정하는 두 가지 방법을 제공하는데 바이트코드를 수정하는 방법은 복잡하다.
프록시의 기초
JPA 에서 식별자로 엔티티를 하나 조회할 때
EntityManger.find();
or repository -> findById();
이 메소드는 영속성 컨텍스트에 엔티티가 없으면 데이터베이스를 조회한다.
엔티티를 조회하면 해당 엔티티는 실제 사용하든 사용하지 않든 데이터베이스를 조회하게 된다. 엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루고 싶으면 EntityManager.getReference() 메소드를 이용하면 된다.
실제 이 메소드를 실행하면
다음과 같은 프록시 객체가 생성된다.
프록시 객체는 실제 객체의 대한 참조를 보관한다. 그리고
프록시 객체의 메소드를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다.
프록시 객체는 Proxy.getName() 처럼 실제 사용될 때 데이터베이스를 조회해서 실제 엔티티 객체를 생성하는데 이것을 프록시 객체의 초기화라 한다.
class Proxy extends Entity {
Entity target = null;
public String getName() {
if(target == null){
1 초기화 요청
2 DB 조회
3 실제 엔티티 참조 보관
this.target = (result)
}
return target.getName()
}
}
만약 영속성 컨텍스트가 종료된 시점에 ( 준영속 상태 )
엔티티의 프록시에 해당 메소드를 호출하면 위와 같은 초기화 과정을 거쳐야하지 못하기 때문에 예외가 발생한다.
그 예외가 우리가 흔히 테스트 코드에서 실수로 보게되는 LazyInitalizationException 이다.
추가 )
엔티티를 프록시로 조회할 때 식별자 ( PK ) 값을 파라미터로 전달하는데 프록시 객체는 이 식별자 값을 보관한다.
프록시 객체는 식별자 값을 가지고 있으므로 만약 식별자 값을 조회하는
getId() 를 호출해도 프록시를 초기화 하지 않는다.
단, 엔티티 접근 방식을 프로퍼티 ( @Access(AccessType.PROPERTY)) 로 설정한 경우에만 초기화하지 않는다.
엔티티 접근 방식을 필드( @Access(AccessType.FIELD )) 로 설정하면 JPA 는 프록시객체를 초기화 한다.
'개발 > java' 카테고리의 다른 글
JPA 2차 캐시란 (0) | 2020.04.26 |
---|---|
JPA 락 (0) | 2020.04.25 |
Java Collection 프레임워크 (0) | 2020.03.22 |
heap 메모리와 Garbage Collector (1) | 2020.03.21 |
spring 에서 pageable custom 구현 (0) | 2019.12.19 |
댓글