해결된 질문
작성
·
186
1
10분 40초 부분의 getReference()
조회 시, Id 값은 이미 있기 때문에 쿼리가 날아가지 않는다는 것에 대한 의문입니다.
우선, 의문이 들었던 지점입니다.
Member 엔티티의 Id를 GeneratedValue 방식 사용하는 상황에서,
1 em.persist(member) ;
2
3 em.flush();
4 em.clear();
5
6 em.getReference(Member.class, member.getId());
7
8 System.out.println("findMember.id = " + findMember.getId());
위와 같은 코드를 실행했을 때 상황입니다.
1) 제가 이해한 위 코드 실행시 발생하는 일을 순서대로 정리해보면:
1행: em.persist(member);
(1) DB의 전략에 따라 DB에서 ID값을 generate하고,
(2) 생성된 ID값이 1차캐시의 key로 저장된다.
4행: em.clear();
(1)영속성 컨텍스트가 완전히 비워진다: 즉 1차 캐시에 저장된 Id값도 비워진다.
6행: em.getReference(Member.class, member.getId());
(1)1차캐시에서 id값을 찾음
(2)4행의 (1)로 인해서 캐시에서 Id 값을 찾을 수 없기에 DB에 SELECT 쿼리를 던지게 된다.
2) 때문에 "Id값이 이미 있기 때문에 INSERT 쿼리가 날아가지 않는다"는 것이 이해가 되지 않습니다.
구체적으로 궁금한 것은
(1) 위에서 말하는 저장된 id값이 어떻게 저장되었냐는 것입니다.
(2) id값이 이렇게 저장되는 것은 어느 시점에서 이루어졌냐는 것입니다.
두 문제에 대한 제 생각은
(1)
영속성 컨텍스트에 저장된 것이 아니고,
member 인스턴스의 변수 member.id가 다른 인스턴스 변수들처럼 관리되어서 저장된 것이다.
(즉 우리가 비영속 상태의 인스턴스 book에 book.setName("Jpa")하는 식으로 값을 저장할 때처럼 저장되는 것이다)
(2)
1행의 (2), 즉 1차캐시의 key로 저장되는 시점에 저장되었다.
인데, 이 이해가 적절한 것인지 궁금합니다.
즉, <영속화되는 엔티티의 id값은 DB에서 생성되어, 1차캐시에 저장되는 시점에 인스턴스 변수에 저장된다.>
그리고 <그 id값은 해당 인스턴스와 동일한 생명 주기를 갖는다>가 적절한 이해인지 궁금합니다.
답변 1
3
안녕하세요. 이한빈님
(1) 위에서 말하는 저장된 id값이 어떻게 저장되었냐는 것입니다.
(2) id값이 이렇게 저장되는 것은 어느 시점에서 이루어졌냐는 것입니다.
-> em.getReference(id)를 호출하는 시점에 영속성 컨텍스트에는 가짜 프록시 객체가 영속성 컨텍스트에서 관리됩니다. 그리고 이 가짜 프록시는 em.getReference()를 호출하는 시점에 id를 전달 받아서 가지고 있습니다.
감사합니다.