inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

173만명의 커뮤니티!! 함께 토론해봐요.

섹션 3 지연 로딩 설정 후 MemberTest 실행 후 쿼리 문

해결됨

실전! 스프링 데이터 JPA

이전 강의를 수강 하면서 엔티티 조회 시 지연 로딩 설정 시 즉시 조회가 되는 게 아닌 프록시 객체가 데이터의 위치를 가지고 사용할 때에 프록시 객체가 초기화 되며 데이터베이스에 쿼리를 요청하고 데이터를 받아 온다 라고 배웠습니다. 그렇다면 테스트 메서드를 실행하게 된다면 Team, Member 객체를 persist -> 영속성 컨텍스트에 Member와 Team 존재 flush() -> 영속성 컨텍스트에 들어있던 엔티티를 데이터베이스에 반영 -> insert 쿼리가 실행 데이터베이스에 반영되었으나 아직 영속성 컨텍스트에는 값이 존재하는 상태 clear() -> 영속성 컨텍스트에 들어 있는 데이터를 초기화 createQuery로 Member 엔티티를 데이터베이스에서 조회 -> Member에 대한 select 쿼리 실행 영속성 컨텍스트가 초기화 되었고 team이 지연 로딩으로 설정되어 프록시 객체가 생성 루프를 돌며 getTeam() 호출 시점 team_id를 기반으로 데이터베이스에 team을 조회 -> Team에 대한 select 쿼리 실행 memberA 조회 후 teamA에 대한 조회 쿼리가 발생하고 memberC 조회 후 teamB 조회 쿼리가 발생 이러한 과정으로 이뤄진다고 배웠는데 테스트 코드를 돌려보니 member에 대한 조회 쿼리 후 team에 대한 조회 쿼리가 발생하지 않습니다. 그래서 팀의 프록시 객체가 초기화 되었는지 체크하기 위해 Hibernate.isInitialized를 사용해 찍어봤는데 제일 처음 false 로 초기화 되지 않았다고 나오나 team을 조회하는 쿼리가 발생하지 않았습니다. 찾다 보니 Hibernate에 쿼리 최적화 기능으로 영속성 컨텍스트는 초기화 되었지만 메모리가 초기화 된 것은 아니므로 해당 객체가 메모리에 존재한다면 Hibernate가 쿼리를 생략하고 해당 객체를 반환한다라는 게 있던데 그것 때문에 쿼리가 나가지 않는 건지 궁금합니다. 2차 캐시가 설정되어 있지는 않습니다. 스프링 부트 3.3.4, 자바 17, Hiberante 6.5.3 입니다! * 해결 * spring.jpa.properties.hibernate.show_sql=true 하이버네이트 show_sql이 주석처리 format_sql만 출력되는 상황이었습니다. 정상 출력 확인했습니다! package springPJ.dataJpa.domain; import jakarta.persistence.EntityManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.hibernate.Hibernate; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @Transactional @RequiredArgsConstructor @Slf4j class MemberTest { @Autowired EntityManager em; @Test void testEntity() { Team teamA = Team.builder().name("teamA").build(); Team teamB = Team.builder().name("teamB").build(); em.persist(teamA); em.persist(teamB); Member memberA = Member.builder().name("memberA").age(10).team(teamA).build(); Member memberB = Member.builder().name("memberB").age(20).team(teamA).build(); Member memberC = Member.builder().name("memberC").age(30).team(teamB).build(); Member memberD = Member.builder().name("memberD").age(40).team(teamB).build(); em.persist(memberA); em.persist(memberB); em.persist(memberC); em.persist(memberD); em.flush(); em.clear(); List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList(); for (Member member : members) { log.info("team.isInitialized = {}", Hibernate.isInitialized(member.getTeam())); log.info("member = {}", member); log.info("member.team = {}", member.getTeam()); } } } select m1_0.member_id, m1_0.age, m1_0.name, m1_0.team_id from member m1_0 2024-09-21T19:36:05.194+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : team.isInitialized = false 2024-09-21T19:36:05.194+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member = Member(id=1, name=memberA, age=10) 2024-09-21T19:36:05.197+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member.team = Team(id=1, name=teamA) 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : team.isInitialized = true 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member = Member(id=2, name=memberB, age=20) 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member.team = Team(id=1, name=teamA) 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : team.isInitialized = false 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member = Member(id=3, name=memberC, age=30) 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member.team = Team(id=2, name=teamB) 2024-09-21T19:36:05.219+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : team.isInitialized = true 2024-09-21T19:36:05.220+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member = Member(id=4, name=memberD, age=40) 2024-09-21T19:36:05.220+09:00 INFO 7696 --- [dataJpa] [ Test worker] springPJ.dataJpa.domain.MemberTest : member.team = Team(id=2, name=teamB)

  • java
  • spring
  • spring-boot
  • jpa
  • fetchtype.lazy
  • 지연로딩
  • 프록시초기화
kwang2134 댓글 1 좋아요 0 조회수 147

인기 태그

인프런 TOP Writers

주간 인기글