member와 team은 지연로딩 관계이다. 따라서 team의 데이터를 조회할때(1번), member를 조회하는 쿼리가 실행된다(n번)

 

-참고: 지연로딩 여부 확인하는 방법 

//Hibernate 기능으로 확인
Hibernate.isInitialized(member.getTeam())
  
//JPA 표준 방법으로 확인
PersistenceUnitUtil util = em.getEntityManagerFactory().getPersistenceUnitUtil(); 
util.isLoaded(member.getTeam());

 

위의 1+N 문제를 해결하기 위해서는 페치 조인이 필요하다 

 

-@EntityGraph

연관된 엔티티들을 SQL 한번으로 조회하는 방법으로, 페치 조인의 간편 버전이다

LEFT OUTER JOIN을 사용한다 

//공통 메서드 오버라이드
@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)

 

-참고:

즉시로딩으로 findAll()을 조회하면 내부에서 left outer join이 걸리지 않음-> findAll()은 JPQL 쿼리가 나간다. JPQL쿼리가 실행되면, JPA는 JPQL 쿼리에 최적화를 실행하지 않는다 

즉시로딩으로 findById()로 처리하면 left outer join이 걸림-> em.find() 메서드가 호출되고, 이때 즉시로딩으로 설정되어있으면 left outer join으로 최적화가 진행된다 

 

--> 되도록이면 지연로딩을 사용하자 

 

+ Recent posts