인프런 커뮤니티 질문&답변

gorany님의 프로필 이미지

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

프록시

프록시 객체 초기화 중 질문있습니다.

해결된 질문

21.07.23 18:50 작성

·

355

4

안녕하세요 영한님! 강의 내용 중 궁금한 점이 있어 질문 드립니다.

Team refTeam = em.getReference(Team.class, 1L);
refTeam.getName();

을 하게되면 Proxy가 비어있으므로

1. 영속성 컨텍스트에 초기화 요청을 보내고,

2. 영속성 컨텍스트가 DB를 조회해

3. 실제 엔티티 객체를 생성

은 이해가 되었습니다.

그럼 여기서 영속성 컨텍스트가 실제 엔티티 객체를 생성하고 Proxy의 target에 연결을 해줄 뿐이지,  1차 캐시에 실제 엔티티가 저장되는 것은 아닌 건가요? 1차 캐시에는 'Proxy 객체만' 있고 Proxy의 target을 통해 실제 엔티티를 접근할 수 있는 건지 궁금하여 질문 드립니다!

감사합니다.

답변 2

4

David님의 프로필 이미지

2021. 07. 23. 21:04

안녕하세요. gorany님, 공식 서포터즈 David입니다.
.

1. 영속성 컨텍스트는 먼저 1차 캐시에 저장 후 영속상태의 엔티티를 반환합니다. 

2. 1차 캐시에는 프록시 객체가 아닌 엔티티가 들어있습니다.

getReference()할 때 proxy 객체를 받았고, getName()할 때 영속성 컨텍스트에 엔티티가 없으면 조회한 뒤 1차캐시에 엔티티를 저장하고 proxy의 target에는 엔티티의 참조가 들어가게 됩니다.

.
감사합니다.

David님의 프로필 이미지

2021. 07. 24. 14:51

영속성 컨텍스트에 Proxy를 담고 있는 Map이 있습니다. Key는 Enity의 id를 사용하고요.

.

1. em.getReference(Member.class, 1L)를 하게 되면 내부에 프록시가 있는 확인합니다.

2. 프록시가 없으면 프록시를 생성하고 반환합니다. 이 과정에서 영속성 컨텍스트는 프록시를 따로 보관하는 맵에 생성된 프록시를 Key(member의 id)와 함께 담습니다.

3. 두 번째로 em.find(Member.class, 1L)를 명령하면 엔티티를 반환하기 전에 프록시를 먼저 찾습니다. em.reference() 명령 때 만들어두었던 프록시가 있기 때문에 프록시를 반환합니다.

.

gorany님의 프로필 이미지
gorany
질문자

2021. 07. 24. 20:14

오.. 이런 내부구조가 있었군요 완전히 이해되었습니다! 친절한 설명 너무 감사드립니다. :)

0

gorany님의 프로필 이미지
gorany
질문자

2021. 07. 24. 14:27

답변 감사드립니다! 제가 잘못 이해하고 있던 부분인 것 같습니다.

Entity entity = getReference(...)

-> 영속성 컨텍스트에 Proxy 저장

-> entity에 Proxy 반환

으로 생각하고 있었는데 getReference() 호출 시,

1. 영속성 컨텍스트에서 값이 있는지 확인 (있다면 그것을 반환)

2. 없다면 Proxy 객체를 반환 (이 때 영속성 컨텍스트에는 아무것도 저장되지 않음)

3. entity.getName()으로 Proxy 초기화 시, 이때 DB를 조회해 생긴 '실제 엔티티가 1차 캐시에 저장'되고, 실제 엔티티를 Proxy의 target이 참조

라고 이해하면 될까요?

만약 그렇다면... 조금 주제를 벗어난 질문이지만,

Q. 동일한 영속성 컨텍스트에서, '다시 동일한 데이터를 find() 해도 Proxy를 반환해준다' 하셨는데 JPA는 어떻게 Proxy를 먼저 반환했던 것을 기억하고 Proxy를 반환해주는 것 인지 궁금합니다.

gorany님의 프로필 이미지

작성한 질문수

질문하기