[JPA] 프록시를 이용한 즉시로딩과 지연로딩

동동·2022년 4월 23일
0

JPA

목록 보기
10/18
post-thumbnail

📌 지연 로딩 LAZY를 사용해서 프록시로 조회

@ManyToOne(fetch = FetchType.LAZY)
연관관계 맵핑 어노테이션에 fetch 속성을 부여해서 사용함
fetch 속성을 LAZY로 주게 되면 해당 클래스를 프록시 객체로 조회
그리고 실제 그 객체가 사용될 때 DB에서 실제 그 값을 가지고 옴

// Member만 DB에서 실제 값을 가져옴
Member m = em.find(Member.class, member1.getId());

// Team 엔티티를 프록시로 조회
System.out.println("m = " + m.getTeam().getClass());

// 직접적으로 Team에 조회가 있는 순간 DB에서 실제 값을 가져옴
m.getTeam().getName();

team을 가져올 때가 아니라 team에 있는 값을 사용할 때 DB에서 실제 값을 가져옴

📌 즉시 로딩 EAGER를 사용해서 함께 조회

Member 엔티티를 가져올 때 Team 엔티티도 함께 가져옴

🚨 Proxy와 즉시로딩 주의

  • 가급적 지연 로딩만 사용(특히 실무에서)
  • 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
  • 즉시 로딩은 JPQL에서 N+1 문제를 일으킴
  • @ManyToOne / @OneToOne 매핑은 기본이 즉시 로딩
  • @OneToMany / @ManyToMany는 기본이 지연 로딩

테이블이 엄청 많을 경우 join 쿼리로 가져 온다면 과부하(성능이 나오지 않음)

JPQL에서 N+1 문제가 일어나는 이유는

List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();

위와 같은 코드를 실행했을 경우 JPQL은 코드를 일단 SQL로 직역을 함.
따라서 select from member;라는 쿼리를 날리게 됨
근데 team이 즉시 로딩(EAGER)로 설정되어 있을 경우. 즉시로딩은 로딩이 될 때 값이 다 들어가 있어야 된다.
따라서 추가로 select
from team; 쿼리를 또 날리게 됨

실무 Tip )

  • 모든 연관관계에 지연 로딩을 사용
  • JPQL fetch 조인이나, 엔티티 그래프 기능을 사용
  • 즉시 로딩은 상상하지 못한 쿼리가 나감(즉시 로딩 사용X)
profile
괴발개발

0개의 댓글