Spring

[JPA] 일반 Join과 Fetch Join의 차이

728x90

Spring Data JPA(이하 줄여서 JPA)를 사용하다보면 연관 관계 맵핑이 된 엔티티를 사용하면서 N+1의 문제를 마주하고는 합니다.

 

예를 들어 우리가 보통 DB에서 연관 맵핑 관계를 볼때는 join 문을 사용해서 쿼리를 만들지만 이상하게 JPA repository로 엔티티를 호출하면 연관된 맵핑만큼 select 쿼리가 만들어집니다 바로 N+1번 쿼리가 진행되는것이죠.

 

이때 보통 아래 코드처럼 fetch join 이 들어간 JPQL 코드를 작성해서 문제를 해결합니다

@Query("SELECT distinct t FROM Team t join fetch t.members")
public List<Team> findAllWithMemberUsingFetchJoin();

왜 일반 join으로는 해결을 못할까요? 꼭 fetch join을 써야하나요?

 

둘의 차이는 다음과 같습니다

  • 일반 Join
    • Join은 fetch join과 다르게 쿼리에서는 join으로 조회해도, 영속성 컨텍스트에는 조회의 주체가 되는 엔티티만 불러오게 됩니다.
    • 만약 즉시로딩, 지연로딩 글을 예시로 든다면, Student엔티티를 불러올때 join 문으로 쿼리를 하기 때문에 N+1번 쿼리를 조회하는 문제는 없어지겠지만 실제로 영속성 컨텍스트에는 Classroom 엔티티는 들어오지 않기 때문에 엔티티를 온전히 사용할 수 없게됩니다. -> LazyInitializationException 이 발생합니다
    • 따라서 실제로 데이터는 필요하지 않지만 연관 Entity가 검색조건에는 필요한 경우에 사용됩니다.
  • Fetch Join
    • Fetch Join은 join 이 걸린 모든 연관 Entity를 영속성 컨텍스트에 저장합니다. 따라서 위와 같은 문제가 발생하지 않습니다.
    • Fetch Join이 걸린 Entity 모두 영속화하기 때문에 FetchType이 Lazy인 Entity를 참조하더라도
      이미 영속성 컨텍스트에 들어있기 때문에 따로 쿼리가 실행되지 않은 채로 N+1문제가 해결됨

 

 

출처:
- [JPA] 일반 Join과 Fetch Join의 차이
728x90