ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Data JPA, N + 1
    개발/Java 2024. 2. 21. 23:44

     

    데이터베이스 구조.

     

    category table
    food table

     

     

    엔티티.

     

     

    fetch의 기본 값은 EAGER.

     

    컨트롤러에서 먼저 category를 가져와보자.

     

    실행하면,

     

    쿼리는 한번만 실행되고,

    기대한 결과가 나온다.

     

    컨트롤러에서 food를 가져오면,

     

     

    여기서 N + 1 이슈가 발생.

    쿼리를 보면 먼저 food를 가져오고 연관된 엔티티 category의 컬럼 수만큼 쿼리를 실행한다.

     

     

    결과는 어쨌든 기대한 결과가 나온다.

    EAGER이 이렇고 이제 fetch 전략을 바꿔보자.

     

     

    무한루프에 빠지기 때문에 여러 방법이 있지만 여기선 일단 JsonIgnore를 붙여주고, 이렇게 food 엔티티의 fetch를 LAZY, 지연로딩으로 바꿔주면 컨트롤러의 로직을 똑같이 요청할 때 쿼리를 한번만 실행한다.

     

     

    결과를 보면 카테고리 엔티티가 빠져있다.

    컨트롤러 로직에 카테고리 엔티티를 쓰지 않고 있기 때문에 쿼리를 실행시키지 않고 가져오지 않은 것.

     

     

    이렇게 food 엔티티에 연관된 카테고리를 불러와서 사용하는 로직이 포함되면,

     

     

    사용할 때 쿼리를 실행한다. 로직에 하나 추가했으니 쿼리도 하나 더 날리는 것. 전부를 추가하면 EAGER과 마찬가지로 결국 쿼리 전부를 실행시킨다.

     

    해결 1. Join Fetch.

     

     

    이렇게 메서드를 직접 만들고 쿼리문을 작성해주는 것.

     

     

    컨트롤러에서 실행해주자. fetch 전략은 EAGER로 수정.

     

     

    쿼리는 한 번 실행되고, ( inner join )

     

     

    바라던 결과가 나왔다.

     

     

    해결 2. EntityGraph.

     

     

    이런 문법으로 사용할 수 있다.

     

     

    쿼리는 한 번만 실행되고 결과도 같다. 실행된 쿼리를 보면 EntityGraph 방식은 outer join을 사용한다.

     

Designed by Tistory.