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의 차이
'Spring' 카테고리의 다른 글
[JPA] OneToMany(1:N) 페이징 처리 (0) | 2022.10.12 |
---|---|
[JPA] @EntityGraph 란? (0) | 2022.10.12 |
[JPA] 즉시 로딩(FetchType.EAGER)과 지연 로딩(FetchType.LAZY) (0) | 2022.10.12 |
[Spring Boot] AutoConfiguration 이란? (1) | 2022.10.12 |
[JPA] 영속성 컨텍스트(Persistence Context)란? (1) | 2022.10.11 |