본 문서는 인프런의 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 (김영한) 강의를 공부하며 작성한 개인 노트입니다.
간단한 주문 조회
지연 로딩 때문에 발생하는 성능 문제를 단계적으로 해결해보자
XToOne의 최적화 (ex) ManyToOne, OneToOne
@GetMapping("/api/v1/simple-orders")
public List<Order> ordersV1() {
List<Order> all = orderRepository.findAllByString(new OrderSearch());
return all;
}
문제 1: 무한 루프
@JsonIgnore
에노테이션 추가문제 2:
문제 3:
@Bean
Hibernate5Module hibernate5Module() {
Hibernate5Module hibernate5Module = new Hibernate5Module();
//강제 지연 로딩 설정
hibernate5Module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true);
return hibernate5Module;
}
OR
@GetMapping("/api/v1/simple-orders")
public List<Order> ordersV1() {
List<Order> all = orderRepository.findAllByString(new OrderSearch());
for (Order order : all) {
order.getMember().getName();
order.getDelivery().getAddress();
}
return all;
}
order.getMember().getName()
과 order.getDelivery().getAddress()
을 통해 지연로딩임에도 디비에서 데이터를 가져온다 결론:
DTO 클래스
@Data
static class SimpleOrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
public SimpleOrderDto(Order order) {
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
}
}
order.getMember().getName();
등을 통해 지연로딩 초기화DTO를 사용한 컨트롤러
@GetMapping("api/v2/simple-orders")
public List<SimpleOrderDto> ordersV2() {
List<Order> orders = orderRepository.findAllByString(new OrderSearch());
List<SimpleOrderDto> result = orders.stream()
.map(SimpleOrderDto::new)
.collect(Collectors.toList());
return result;
}
문제점
order -> member
지연로딩 조회 N번 > order -> delivery
지연로딩 조회 N번public List<Order> findAllWithMembersDelivery() {
return em.createQuery(
"select o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d", Order.class
).getResultList();
}
컨트롤러
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4() {
return orderRepository.findOrderDto();
}
DTO 클래스 생성
@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;
}
}
OrderRepository.class에 만듬
public List<OrderSimpleQueryDto> findOrderDto() {
return em.createQuery("selectnew jpabook.jpashop.repository.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address) " +
" join o.member m" +
" join o.delivery d", OrderSimpleQueryDto.class)
.getResultList();
}
SELECT
절에서 원하는 데이터만 조회 > 애플리케이션 네트워크 용량 최적화 (미비)new
명령어로 JPQL 결과를 즉시 DTO 변환select
문은 필요한 테이블만 건듬