본문 바로가기

JPA

[JPA] 프록시란?

예를 들어)

Member와 Team이 연관 관계를 가지고 

비즈니스 로직을 설계할 때 member의 내용만 가져오고 싶어서 코드를 작성했더니

실제 쿼리에서는 Member와 Team 둘 다 가져오는 쿼리가 나가게 되기 때문에 이것을 최적화라고 볼 수 없다...

이것을 해결하기 위해 지연로딩을 설정해야 하는데 지연 로딩을 이해하기 위해서는 프록시를 이해하는 것이 우선이다.

 

프록시

DB에서 데이터를 조회하는 방법으로 find와 getReferece가 있다.

 

- em.find() :  데이터베이스를 통해서 실제 엔티티 객체 조회

- em.getReference()  :  데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회

즉, 결론적으로 디비에 쿼리가 안 나가는데 조회가 되는 것이다.

find와 달리 select문이 나가지 않는다.

실제로 조회 (사용되는 시점)에서 쿼리가 이제야 나가는 것을 알 수 있다.

여기서 ID값은 이미 출력이 되고 나서 쿼리가 나가는 것을 알 수 있는데 그 이유는

레퍼런스를 찾을 때 아이디 값을 넣어서 찾기 때문에 쿼리가 나가지 않고 username은 db에 있기 때문에 쿼리가 나가는 것이다.

 

getClass를 이용하여 클래스를 알아보면 프록시 클래스라는 것을 알 수 있다.

 

그럼 프록시란?

- 실제 클래스를 상속받아서 만들어진다.

- 실제 클래스와 겉모양이 같다.

getReference를 하면 프록시 가짜 엔티티를 가져다주는데 target이 진짜 레퍼런스를 가리키며 초기에는 null 값이다.

 

- 프록시 객체는 실제 객체의 참조를 보관한다.

- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출

 

 

프록시 객체의 초기화

getReference를 사용해서 getName를 호출한다고 하면 과정이 이렇게 된다.

getName을 호출하면 프록시에는 값이 없기 때문에 영속성 컨텍스에게 부탁해 DB를 조회하여서 실제 엔티티를 생성하면,

프록시 객체가 진짜 레퍼런스를 참조하며 값을 저장하게 된다.

 

그렇기 때문에 한번 값을 호출해서 초기화를 하면 프록시 객체에는 그 값이 저장이 되어있기 때문에 더 이상 쿼리를 실행하지 않는다.

 

 

출처 - www.inflearn.com/course/ORM-JPA-Basic

'JPA' 카테고리의 다른 글

[JPA] 페치조인(fetch join)이란?  (0) 2021.01.21
[JPA] 지연 로딩과 즉시 로딩  (2) 2021.01.09
상속관계 매핑  (0) 2020.12.22
연관관계 매핑  (0) 2020.12.22
엔티티 매핑  (1) 2020.12.21