간단한 주문 조회 v3 ~ v4
v3 - 엔티티를 DTO로 변환 - 페치 조인 최적화
1
2
3
4
5
6
7
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 사용
딱 한 개의 쿼리만 잘 나간 걸 볼 수 있다.
v4 - JPA에서 DTO로 바로 조회
먼저 dto 클래스 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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;
}
}
Repository 단에서 v4용 쿼리를 작성 → 진짜 필요한 데이터만 직접 dto 에 넣어서 사용
이렇게 되면 리포지토리단에 api 스펙이 의존된다..
1 2 3 4 5 6 7 public List<OrderSimpleQueryDto> findOrderDtos() { return em.createQuery( "select new jpabook.jpashop.repository.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(); }
1
2
3
4
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4() {
return orderRepository.findOrderDtos();
}
컨트롤러 호출 시
select 절이 확실히 줄어 들었다..
그런데 Repository 단에 쿼리가 많이 복잡해지긴 했다.
v4 정리
- 일반적인 SQL을 사용할 때 처럼 원하는 값을 선택해서 조회
new명령어를 사용해서 JPQL의 결과를 DTO로 즉시 반환- SELECT 절에서는 원하는 데이터를 직접 선택하므로 DB → 애플리케이션 네트웍 용량 최적화 (생각보다 미비…)
- 리포지토리 재사용성 떨어짐, API 스펙에 맞춘 코드가 리포지토리에 들어가는 단점..
정리
엔티티를 DTO로 변환하거나, DTO로 바로 조회하는 두 가지 방법은 각각 장단점이 있다. 둘중 상황에 따라서 더 나은 방법을 선택하면 된다. 엔티티로 조회하면 리포지토리 재사용성도 좋고, 개발도 단순해진다. 따라서 권장하는 방법은 다음과 같다.
쿼리 방식 선택 권장 순서
- 우선 엔티티를 DTO로 변환하는 방법을 선택한다.
- 필요하면 페치 조인으로 성능을 최적화 한다. → 대부분의 성능 이슈가 해결된다.
- 그래도 안되면 DTO로 직접 조회하는 방법을 사용한다.
- 최후의 방법은 JPA가 제공하는 네이티브 SQL이나 스프링 JDBC Templete 을 사용하여 SQL을 직접 사용한다.
댓글남기기