N+1 문제

 

User 를 조회 시 board 도 함께 조회가 된다.

@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
@JsonIgnore
private List<Board> boards = new ArrayList<>();
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.enabled as enabled2_2_,
        user0_.password as password3_2_,
        user0_.username as username4_2_ 
    from
        user user0_
Hibernate: 
    select
        boards0_.user_id as user_id4_0_0_,
        boards0_.id as id1_0_0_,
        boards0_.id as id1_0_1_,
        boards0_.content as content2_0_1_,
        boards0_.title as title3_0_1_,
        boards0_.user_id as user_id4_0_1_ 
    from
        board boards0_ 
    where
        boards0_.user_id=?
Hibernate: 
    select
        boards0_.user_id as user_id4_0_0_,
        boards0_.id as id1_0_0_,
        boards0_.id as id1_0_1_,
        boards0_.content as content2_0_1_,
        boards0_.title as title3_0_1_,
        boards0_.user_id as user_id4_0_1_ 
    from
        board boards0_ 
    where
        boards0_.user_id=?

 

 

이를 해결 하기 위해 FetchType.LAZY 로 변경해준다.

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
@JsonIgnore
private List<Board> boards = new ArrayList<>();
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.enabled as enabled2_2_,
        user0_.password as password3_2_,
        user0_.username as username4_2_ 
    from
        user user0_

결과는 user select 만 호출 된다.

 

LAZY 상태에서 board 에 접근하게 되면 그때서야 board를 호출한다.

@GetMapping("/users")
List<User> all() {
    List<User> users = userRepository.findAll();
    users.get(0).getBoards().size();
    return users;
}
Hibernate: 
    select
        user0_.id as id1_2_,
        user0_.enabled as enabled2_2_,
        user0_.password as password3_2_,
        user0_.username as username4_2_ 
    from
        user user0_
Hibernate: 
    select
        boards0_.user_id as user_id4_0_0_,
        boards0_.id as id1_0_0_,
        boards0_.id as id1_0_1_,
        boards0_.content as content2_0_1_,
        boards0_.title as title3_0_1_,
        boards0_.user_id as user_id4_0_1_ 
    from
        board boards0_ 
    where
        boards0_.user_id=?

추가로 board 를 호출한다.

 

 

 

LAZY 타입 때 board 까지 한 번에 조회 되게 하자

 

@EntityGraph 어노테이션을 UserRepository 에 추가한다.

public interface UserRepository extends JpaRepository<User, Long> {

    @EntityGraph(attributePaths = { "boards" })
    List<User> findAll();

    User findByUsername(String username);
}
Hibernate: 
    select
        user0_.id as id1_2_0_,
        boards1_.id as id1_0_1_,
        user0_.enabled as enabled2_2_0_,
        user0_.password as password3_2_0_,
        user0_.username as username4_2_0_,
        boards1_.content as content2_0_1_,
        boards1_.title as title3_0_1_,
        boards1_.user_id as user_id4_0_1_,
        boards1_.user_id as user_id4_0_0__,
        boards1_.id as id1_0_0__ 
    from
        user user0_ 
    left outer join
        board boards1_ 
            on user0_.id=boards1_.user_id

 

복사했습니다!