DevBoi

[JPA] 프록시객체에 대한 이해 본문

Develop/[JPA]

[JPA] 프록시객체에 대한 이해

HiSmith 2022. 2. 17. 01:10
반응형

Member와 Member 하위의 Team이라는 객체가 있다고 가정해보자

그리고, Member와 Team 을 둘다 받는 메소드가 있고,

Team은 필요없이 Member만 필요한 경우를 생각해보자

 

실제로, 저장하고 find할때, Insert, select 가 된다.

 

만약에 이렇게 , find가아니라, getReference로 불러올때는 사용하지않으면, select 쿼리, 즉 db에서 조회하지 않는다.

어떻게 가능할까?

 

 우선 getReference로 하면, 하이버네이트에서 내부에서 가짜 엔티티(프록시) 가 만들어진다.

 

 이 가짜 엔티티는 실제 클래스를 상속 받아 겉모양은 같지만, 내부의 값들이 텅텅 비었다.

쉽게 말하면, 키를 가지고 디비를 조회할수 있게끔 아이디값만 가지고 있는 가짜 텅빈 엔티티라고 생각하면된다.

 

이런식으로 생겼고, 만약에 이 프록시 객체를 호출하게 되면, 

타겟에 메소드를 호출해준다.

 

 

클라이언트가 프록시의 getname을 호출하면, 

프록시 객체는 영속성 컨텍스트에 초기화를 요청하게 되고

이 영속성 컨텍스트는 DB를 조회해서, 실제 엔티티를 생성한다. 이 엔티티는 프록시의 타겟 엔티티 이다.

 

쉽게 말하면 프록시 객체를 호출하면, 해당 프록시 객체가 영속성 컨텍스트에 엔티티를 초기화를 요청하는 것이다.

 

프록시 객체의 특징

-프록시 객체는 처음 한번 사용할때 초기화 한다.

-초기화 되면 프록시 객체가 실제 엔티티가 되는것은 아니다. (초기화 이후에도 프록시 객체는 계속 프록시 객체이다) -> 타입 체크시 == 이 아니라 instance of 로 해야한다.

-만약에 프록시에서 찾는 객체가, 영속성 컨텍스트에 있다고 하면, 해당 실제 객체를 반환한다.

 

만약에 getReference로 조회를 하고, 그뒤에 동일 내용을 find하면

find로 가져온 객체도 프록시객체로 가져온다.

jpa는 동일 내용에 대해 가져온 객체에 대한 타입을 맞추려는 경향이 있다.
즉 JPA는 한 트랜잭션에서 같은 객체를 가져온 경우, ==의 결과가 항상 true로 나와야 한다

 

-영속성 컨텍스트의 도움을 받을수 없는 준영속 상태일때 프록시를 초기화 하면 문제가 발생한다.

이렇게 가져오면, refMember에대한 쿼리가 나간다.

 그런데 만약에 해당 프록시 객체를 사용하기전에, 영속성 컨텍스트를 비우는 작업이 있다고 하면, 해당 사용시에는 문제가 발생한다.

 

프록시는 영속성 컨텍스트를 통해db의 값을 가져오는데, 해당 영속성 컨텍스트가 먼저 닫혀 버리면, 프록시는 해당 도움을 받지 못해

오류가 발생한다.(상세 동작 과정은 좀더 알아보자)

 

프록시에서 사용가능한 메서드 들이 있다.

 

1. 프록시 인스턴스의 초기화 여부 확인

 

 

 

2. 프록시 강제 초기화

Hibernate.initalize(obj)

 

실제 특정 속성값을 가져오지 않고, Hibernate.initialize를 사용하면, 강제로 영속성 컨텍스트를 통해 해당 프록시 객체의 타겟 객체를 초기화 할수 있다.

반응형