[JPA 활용2] API 개발 고급 - 지연 로딩과 조회 성능 최적화 ②
[ 간단한 주문 조회 V3: 엔티티를 DTO로 변환 - 페치 조인 최적화 ]
1. OrderSimpleApiController
- V3 추가
/**
* V3. 엔티티를 조회해서 DTO로 변환 (fetch join 사용 O)
* - fetch join으로 쿼리 1번 호출
*/
@GetMapping("/api/v3/simple-orders")
public List<SimpleOrderDto> orderV3() {
List<Order> orders = orderRepository.findAllWithMemberDelivery();
List<SimpleOrderDto> result = orders.stream()
.map(o -> new SimpleOrderDto(o))
.collect(toList());
return result;
}
2. OrderRepository
에 findAllWithMemberDelivery
추가
public List<Order> findAllWithMemberDelivery() {
return em.createQuery(
"select o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d", Order.class)
.getResultList();
}
- 엔티티를 페치 조인(
fetch join
)을 사용해서 쿼리 1번에 조회한다. - 페치 조인으로
order → member, order → delivery
는 이미 조회된 상태이므로 지연로딩 X
실행 결과
- V2는 쿼리가 5번 나갔는데, V3는 쿼리가 딱 한 번만 나간다!
[ 간단한 주문 조회 V4: JPA에서 DTO로 바로 조회 ]
1. OrderSimpleApiController
- V4 추가
/**
* V4. JPA에서 DTO로 바로 조회
* - 쿼리 1번 호출
* - select 절에서 원하는 데이터만 선택해서 조회
*/
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> orderV4() {
return orderSimpleQueryRepository.findOrderDtos();
}
2. OrderSimpleQueryRepository
생성
@Repository
@RequiredArgsConstructor
public class OrderSimpleQueryRepository {
private final EntityManager em;
public List<OrderSimpleQueryDto> findOrderDtos() {
return em.createQuery(
"select new jpabook.jpashop.repository.order.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address)" +
" from Order o" +
" join o.member m" +
" join o.delivery d", OrderSimpleQueryDto.class)
.getResultList();
}
}
new
를 이용해서 객체를 생성할 때full package path
를 입력해야 한다.
3. OrderSimpleQueryDto
생성
@Data
public class OrderSimpleQueryDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //주문 시간
private OrderStatus orderStatus;
private Address address;
public OrderSimpleQueryDto(Long orderId, String name, LocalDateTime orderDate, OrderStatus orderStatus, Address address) {
this.orderId = orderId;
this.name = name;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
this.address = address;
}
}
- 일반적인 SQL을 사용할 때처럼 원하는 값을 선택해서 조회한다.
new
명령어를 사용해서 JPQL의 결과를 DTO로 즉시 변환한다.- SELECT 절에서 원하는 데이터를 직접 선택하므로 DB → 애플리케이션 네트워크 용량 최적화! (생각보다 미비)
- 리포지토리 재사용성이 떨어진다.
실행 결과
📌 정리
엔티티를 DTO로 변환하거나(V3), DTO로 바로 조회하는 방법(V4)은 각각 장단점이 있다. 그래서 사실 우열을 가리기는 힘들다!
V3보다 V4가 성능 최적화는 되었지만, 재사용성이 좋지 않다.
💡 쿼리 방식 선택 권장 순서
- 우선 엔티티를 DTO로 변환하는 방법을 선택한다.
- 필요하면 페치 조인으로 성능을 최적화한다. → 대부분의 성능 이슈가 해결된다.
- 그래도 안되면 DTO로 직접 조회하는 방법을 사용한다.
- 최후의 방법은 JPA가 제공하는 네이티브 SQL이나 스프링 JDBC Template을 사용해서 SQL을 직접 사용한다.
Author And Source
이 문제에 관하여([JPA 활용2] API 개발 고급 - 지연 로딩과 조회 성능 최적화 ②), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mmy789/JPA-활용2-API-개발-고급-지연-로딩과-조회-성능-최적화-a5as1c0r저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)