1개의 쿼리를 생각하고 설계를 했으나 나오지 않아도 되는 조회의 쿼리가 N개가 더 발생하는 문제.

Fetch type은 default로 ~ToMany에서는 Lazy~ToOne에서는 Eager로 지정되어있는데 이런 부분들은 default옵션을 사용한다고 하더라도 명시해주는 것이 협업하는 다른 개발자가 보기에도 좋다.

https://velog.io/@jinyoungchoi95/JPA-모든-N1-발생-케이스과-해결책

Eager로딩 시

모든 User에 대해서 검색하고 싶어서 select 쿼리를 하나 날렸지만**(1), 즉시로딩이 걸려있기 때문에 각각의 User가 가진 Article을 모두 검색한다(N)**라는 N+1 문제가 발생

LAZY로딩 시

지연 로딩은 해당 연결 entity에 대해서 프록시로 걸어두고, 사용할 때 쿼리문을 결국 날리기 때문에 처음 find할 때는 N+1이 발생하지 않지만 추가로 User 검색 후 User의 Article을 사용해야한다면 이미 캐싱된 User의 Article 프록시에 대한 쿼리가 또 발생

일단 즉시로딩에서는 우리가 커스텀할 수 있는 부분이 존재하지 않는다.(EAGER)

하지만 지연로딩 과정에서 우리는 바로 사용을 할 객체에 대해서는 join을 걸 수 있도록 조정할 수 있다.(LAZY)

그것이 fetch join인거죠.

JPQL쿼리문에 @Query(Select disrinct …. left join…)과 같이 넣어도 N+1문제는 발생한다.

여기서 해결책은 fetch join을 걸어버리면 됩니다.

@Query("select distinct u from User u left join fetch u.articles")
List<User> findAllJPQLFetch();

fetch는 지연 로딩이 걸려있는 연관 관계에 대해서 한번에 같이 즉시로딩해주는 구문입니다.(하드 코딩)

또는 아래와 같이 작성한다.

@EntityGraph(attributePaths = {"articles"}, type = EntityGraphType.FETCH)
@Query("select distinct u from User u left join u.articles")
List<User> findAllEntityGraph();