JPA 심화 4-4

5w31892p·2023년 2월 5일
0

JPA 심화

목록 보기
19/19

N+1 문제

  • 엔티티 하나을 조회하기 위해서 1:N 로 연관된 엔티티까지 조회 쿼리문이 N+1번 날라가는 이슈
  • 심각한 성능 저하 일어날 수 있음
  • Comment 조회 - 1번
  • Comment의 갯수(각 Comment가 가지고 있는 Board 조회) - N번

이렇게 하면 N+1번의 쿼리가 발생하는 것

:: N+1 문제 해결방법

  1. GlobalFetch
  2. Fetch Join
  3. EntityGraph

Global Fetch Strategy

  • 엔티티를 생성할 때(컴파일 시점) 결정 되는 연관관계 전략
  • @ManyToOne 속성에 fetch 속성으로 LAZY를 주면 된다
public class Comment {

    ...

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "thread_id")
    Board thread;
}

Fetch Join

  • 조인할 때 연관된 엔티티나 컬렉션를 함께 조회하려고 할 때 사용
  • 결과는 EAGER와 똑같지만, EAGER의 경우에는 N+1 쿼리가 발생하지만 Fetch Join의 경우에는 한번이 쿼리문으로 해결이 가능
  • Spring Data JPA 에서는 @Query 어노테이션을 이용하여 JPQL를 생성할 수 있다
  • 사용하는 방법은 join fetch 뒤에 연관된 엔티티나 컬렉션을 적어주면 된다
public interface CommentRepository extends JpaRepository<Comment, Long> {

    @Query("select c from Comment c join fetch c.board")
    List<Comment> findAll();
}

EntityGraph - 현업 사용 (+ QueryDSL도 현업 사용)

  • @EntityGraph도 마찬가지로 EntityGraph 상에 있는 Entity들의 연관관계 속에서 필요한 엔티티와 컬렉션을 함께 조회하려고 할때 사용
  • Spring Data JPA에서 적용하려는 메소드 위에 @EntityGraph 어노테이션을 달고 옵션을 준다
  • attributePaths는 같이 조회할 연관 엔티티명을 적으면 된다.
  • , (콤마)를 통하여 여러개를 줄 수도 있다
  • type은 EntityGraphType.LOADEntityGraphType.FETCH 2가지
    • LOAD
      • attributePaths에 정의한 엔티티들은 EAGER, 나머지는 글로벌 패치 전략에 따라 패치
      • 일단 attributePaths 는 EAGER, 나머지는 매핑 설정 따라서
    • FETCH 
      • attributePaths에 정의한 엔티티들은 EAGER, 나머지는 LAZY로 패치
      • 나빼고 다 LAZY!!
public interface CommentRepository extends JpaRepository<Comment, Long> {

    @EntityGraph(attributePaths = {"thread"}, type = EntityGraph.EntityGraphType.LOAD)
    List<Comment> findAll();
}

0개의 댓글