작성
·
211
0
답변 2
1
안녕하세요, 김민지 님! 공식 서포터즈 codesweaver 입니다.
JPA에는 Lazy Loading 이라고 하는 최적화기술을 제공합니다.
이는 웹에서 많이 사용하는 개념인데, 아직 쓰지 않을 리소스를 굳이 로드하지 말자는 개념입니다.
비유를 하자면 당장 만원만 필요한데 통장에 있는 잔고를 몽땅 빼올 필요가 없다는 겁니다. (잔고가 만원이면.... 몽땅 빼야겠네요)
만약 모든 코드를 싹 지우고 em.find(Team.class, 1); 로 조회하는 경우를 가정하면 Team의 모든 값들을 채운 객체를 반환합니다. 하지만 List<Member>는 지금 당장 사용할건지 아닌지 JPA 입장에서 알 수 없습니다. (며느리도 모르고, 개발자만 압니다) 그래서 Member에 대한 내용은 제쳐두고 나머지 Team 객체 정보만 조회해서 반환합니다.
이후 Member를 실제로 사용하는 시점이 되면 그제서야 DB에 다시 가서 혹은 영속성 컨텍스트에 있다면 그것을 찾아서 가져옵니다. 이런 방식을 Lazy Loading이라고 합니다.
em.persist()를 한 경우엔 즉시 쿼리를 날립니다.
그래서 데이터를 insert하고 그로 인해 생성한 아이디 값을 이용해 영속성 컨텍스트에 보관합니다.
그래서 다음의 코드를 보면,
Team team = new Team()
team.setName("팀1");
em.persist(team);
-- 이 뒤에
System.out.println(team.getId());
-- 아이디를 조회하면 정상적으로 team의 아이디가 조회됩니다. persist 이후에 즉시 디비에 갔다오기 때문입니다.
감사합니다.
안녕하세요! 이해가 안 되는 부분이 있어 질문 좀 드리겠습니다.. ㅠㅠ
1. Team에서 List<Member>에 조회가 안 되는 이유는 아직 member가 DB에 Insert가 안 된 상태라서 조회가 안 되는 것 아닌가요??
2. em.persist(member)를 하면
1) 1차 캐시에 member 객체를 보관
2) 쓰기 지연 SQL 저장소에 INSERT SQL을 보관
3) 시퀀스 전략에 의해 Id(Key)값 할당
이렇게 되어있다가 flush 또는 트랜젝션 커밋, JPQL 실행하는 시점에 DB에 Insert가 되는거 아닌가요?
1. LazyLoading 설정이라면, member가 데이터베이스에 있는 상태라 하더라도, 엔티티매니저로 team을 찾은 뒤 List<Member>는 빈 콜렉션을 참조하게 됩니다. List<Member>를 구체적으로 사용하는 순간 데이터베이스에서 Member 엔티티를 조회합니다.
2. persist는 말씀하신 과정에서 2)의 과정이 포함되지 않습니다. 즉시 데이터베이스에 다녀오게 됩니다. 그리고 데이터베이스에서 획득한 key를 아이디로 갖게 됩니다.
감사합니다.
안녕하세요 code-tree님!
아이디 생성 전략이 sequence 인 경우 code-tree님 말씀이 맞습니다.
제가 말씀드린 내용은 identity 방식일 경우에만 해당하는 내용입니다.
sequence의 경우 한번에 여러개의 아이디를 획득, 이 아이디가 모두 소진되기 전까진
데이터베이스에 직접 다녀오지 않습니다.