[Spring/Springboot] @EntityGraph
2024. 12. 22. 07:05ㆍCS/Spring

@EntityGraph
- @EntityGraph는 JPA에서 Fetch Join과 유사하게 사용되는 기능
- 엔티티를 조회할 때 연관된 엔티티를 함께 로딩하여 N+1 문제를 해결
- @EntityGraph는 JPQL 쿼리가 아닌, 메서드에 직접 설정 ⇒ 특정 엔티티와 그 연관 엔티티를 한 번에 조회할 수 있도록
- @EntityGraph는 Lazy Loading을 사용하는 연관 엔티티를 즉시 로딩(Eager Loading)으로 바꾸어, 원하는 엔티티와 그 연관된 엔티티를 함께 조회할 수 있도록
- JPA에서는 지연 로딩(Lazy Loading)으로 인해 연관된 엔티티를 사용할 때마다 쿼리가 추가로 발생하는 N+1 문제가 생기는데, @EntityGraph는 이런 문제를 간단하게 해결
@EntityGraph를 사용하는 방법
- @EntityGraph를 사용하여 Review 엔티티를 조회하면서 Store와 Member를 한 번에 가져오는 방법
public interface ReviewRepository extends JpaRepository<Review, Long> {
@EntityGraph(attributePaths = {"store", "member"})
@Query("SELECT r FROM Review r WHERE r.store.name = :storeName")
List<Review> findReviewByStoreName(@Param("storeName") String storeName);
}
- @EntityGraph(attributePaths = {"store", "member"}): Review 엔티티를 조회할 때 store와 member 연관 엔티티를 함께 로딩하도록 설정
- 즉, Review를 조회하는 쿼리를 실행할 때 Store와 Member 엔티티도 한 번에 가져옴
- JPQL에서 JOIN FETCH 생략: @EntityGraph를 사용하면 JOIN FETCH를 사용하지 않고도 연관된 엔티티를 가져올 수 있음
- @EntityGraph가 JOIN FETCH와 같은 역할을 수행
@EntityGraph가 생성하는 쿼리
- @EntityGraph를 적용한 findReviewByStoreName 메서드를 실행하면, JPA는 Review 엔티티와 함께 Store와 Member 엔티티도 한 번에 조회하는 쿼리를 생성
- 예를 들어, storeName이 "요아정"인 경우 다음과 같은 쿼리가 실행
SELECT
r.id, r.body, r.score, r.created_at,
s.id, s.name, s.address, s.score,
m.id, m.name, m.email, m.point
FROM
review r
JOIN
store s ON r.store_id = s.id
JOIN
member m ON r.member_id = m.id
WHERE
s.name = '요아정';
- 이 쿼리는 Review 엔티티와 연관된 Store 및 Member 엔티티를 한 번에 가져와서 추가적인 쿼리를 줄여줌
- 따라서, Review를 조회할 때 Store와 Member 엔티티에 접근하더라도 추가적인 SQL 쿼리가 발생X ⇒ N+1 문제가 발생X
Fetch Join과 @EntityGraph의 차이점
- 코드의 간결함: @EntityGraph는 메서드 위에 어노테이션으로 설정하기 때문에, JOIN FETCH 구문을 사용할 필요 없이 간단하게 연관된 엔티티를 한 번에 조회 가능
- JPQL 쿼리 없이 사용 가능: @EntityGraph는 JPQL 쿼리가 없어도 사용 가능 이는 일반적인 findAll() 같은 기본 메서드와 함께 사용할 때 유용
- 유연성: @EntityGraph는 기본적으로 Lazy로 설정된 연관 엔티티만 Eager로 로딩하므로, 특정 상황에서만 즉시 로딩이 필요할 때 사용 가능
'CS > Spring' 카테고리의 다른 글
[Spring/Springboot] N+1 문제 해결 방안 - Batch Size/2차 캐시/Subselect Fetching/DTO (0) | 2024.12.22 |
---|---|
[Spring/Springboot] QueryDSL이란? (0) | 2024.12.22 |
[Spring/Springboot] Fetch Join (0) | 2024.12.15 |
[Spring/Springboot] JPA 다양한 쿼리 방법 - JPQL/QueryDSL (0) | 2024.12.15 |
[Spring/Springboot] 영속성(Persistence) - 1차 캐시/변경 감지(Dirty Checking)/지연 로딩(Lazy Loading) (0) | 2024.12.15 |