처음 실행한 SQL 외에 연관 데이터를 가져오기 위해 추가 SQL이 실행되는 문제이다.
- 예를 들어 게시글 100개를 조회하고, 각 게시글의 작성자를 확인한다고 가정하자.
게시글 조회: SQL 1회
각 게시글의 작성자 조회: 최대 SQL 100회
총 SQL 실행 횟수: 최대 101회- 실제로는 1+N에 더 가까운 느낌이다.
연관 엔티티를 조회하는 시점 때문이다.
List<Post> posts = postRepository.findAll(); for (Post post : posts) { System.out.println(post.getMember().getName()); } // post의 member는 FetchType.LAZY
- 위 코드에서 처음 findAll은 member를 가져오지 않는다.
- 이후 for문이 getMember를 호출할 때 posts의 크기만큼 sql이 실행된다.
(영속성 컨테이너에 이미 로딩된 member가 있을 경우 sql의 실행 횟수가 줄어들 수 있다)
JPQL에서 연관 데이터를 한 번의 SQL로 가져온다.
@Query(""" SELECT p FROM Post p JOIN FETCH p.member """) List<Post> findAllPosts();
어노테이션을 통해 함께 조회할 연관 엔티티를 선언한다.
@EntityGraph(attributePaths = {"member"}) List<Post> findAll();
DTO를 통해 실제로 필요한 데이터만 조회한다.
@Query(""" SELECT new com.example.dto.PostResponse( p.id, p.title, m.name ) FROM Post p JOIN p.member m """) List<PostResponse> findPostResponses();