저번 기본 편에서 연관된 다른 엔티티에 내용을 조회할 때 문제가 있었다. 실무에서는 모든 내용이 Lazy 로딩으로 되어 있어야 한다. 그 상태에서 연관된 다른 엔티티를 조회할 경우 프락시로 저장되어 있다. 그래서 그 엔티티 내용을 다시 조회할 때면 쿼리가 또 나가게 된다. 결국 N+1 문제가 발생한다. 이것을 해결한 것이 fetch join이다. fetch join은 연관된 엔티티도 조회할 때 클래스로 가지고 온다. 즉, N+1 문제가 해결되고 한방 쿼리로 모든 것을 가져오게 된다.
하지만 스프링 데이터 JPA에서 사용할려면 Query문을 새로 추가해 줘야 하고 매번 fetch join을 써줘야 한다. 그래서 스프링 데이터 JPA에서 지원해주는 것이 @EntityGraph 이다.
EntityGraph 사용 방법
//공통 메서드 오버라이드
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
//JPQL + 엔티티 그래프
@EntityGraph(attributePaths = {"team"})
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
//메서드 이름으로 쿼리에서 특히 편리하다.
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String username)
이렇게 할 경우 내부에서 team과 Member를 패치 조인후에 가져온다.
- 사실상 페치 조인(FETCH JOIN)의 간편 버전
- LEFT OUTER JOIN 사용
NamedEntityGraph 사용 방법
@NamedEntityGraph(name = "Member.all", attributeNodes =
@NamedAttributeNode("team"))
@Entity
public class Member {}
@EntityGraph("Member.all")
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
NamedEntityGraph는 위의 코드 처럼 사용한다.
JPA Hint & Lock
JPA Hint
JPA 쿼리 힌트는 SQL 힌트가 아니라 JPA 구현체에게 제공하는 힌트이다.
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUsername(String username);
Lock
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findByUsername(String name);
select 할 때 건들지 말라고 Lock을 걸수가 있다.
org.springframework.data.jpa.repository.Lock 어노테이션을 사용한다.
출처
'Spring JPA 공부 > 스프링 데이터 JPA' 카테고리의 다른 글
스프링 데이터 JPA 분석 (1) | 2023.01.23 |
---|---|
확장 기능 (0) | 2023.01.23 |
벌크성 수정 쿼리 (1) | 2023.01.20 |
JPA 페이징 처리 (0) | 2023.01.14 |
쿼리 메소드 기능 (0) | 2023.01.14 |