728x90
728x90
※ 본 포스팅은 김영한 강사님의 인프런 '실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화' 강의를 들으며 작성한 수강일지 입니다.
| API 개발 고급 - 컬렉션 조회 최적화
1. 주문 조회 V1: 엔티티 직접 노출
2. 주문 조회 V2: 엔티티를 DTO로 변환
3. 주문 조회 V3: 엔티티를 DTO로 변환 - 페치 조인 최적화
4. 주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파
5. 주문 조회 V4: JPA에서 DTO 직접 조회
6. 주문 조회 V5: JPA에서 DTO 직접 조회 - 컬렉션 조회 최적화
7. 주문 조회 V6: JPA에서 DTO로 직접 조회, 플랫 데이터 최적화
8. API 개발 고급 정리
3. 주문 조회 V3: 엔티티를 DTO로 변환 - 페치 조인 최적화
- fetch join : DB 입장에서는 order는 2개인데 join하는 order_item은 4개라 order가 4개가 되어버림(1:N이면 N만큼 데이터가 뻥튀기 됨) -> dinstinct 걸어주기
OrderApiController에 추가
@Getter
static class OrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //주문시간
private OrderStatus orderStatus;
private Address address; // Entity를 다 노출하면 안됨, but Address 같은 value object는 상관없음
private List<OrderItemDto> orderItems;
// 생성자
public OrderDto(Order order) {
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
orderItems = order.getOrderItems().stream() // loop로 돌리면서
// .map(OrderItemDto::new)
.map(orderItem -> new OrderItemDto(orderItem)) // 생성자를 통해 dto로 변환
.collect(Collectors.toList());
}
}
OrderRepository에 추가
// for v3
public List<Order> findAllWithItem() {
return em.createQuery("select distinct o from Order o" + // order 자체가 4개가 나오므로 distinct 추가(sql문과 동일한 distinct 효과 + entity가 중복인 경우 걸러서 collection에 담아줌)
" join fetch o.member m" +
" join fetch o.delivery d" +
" join fetch o.orderItems oi" + // 4개
" join fetch oi.item i", Order.class)
// .setFirstResult(1) // 1:N에 jetch join을 건 순간 이런 페이징 불가
// .setMaxResults(100)
.getResultList(); // order가 4개가 되어버림
}
- 페치 조인으로 SQL이 1번만 실행됨
- distinct 를 사용한 이유는 1대다 조인이 있으므로 데이터베이스 row가 증가한다. 그 결과 같은 order 엔티티의 조회 수도 증가하게 된다. JPA의 distinct는 SQL에 distinct를 추가하고, 더해서 같은 엔티티가 조회되면, 애플리케이션에서 중복을 걸러준다. 이 예에서 order가 컬렉션 페치 조인 때문에 중복 조회 되는 것을 막아준다.
- 단점
- 페이징 불가능 !! (1 대 N을 fetch join 하는 순간 페이징 안됨)
참고: 컬렉션 페치 조인을 사용하면 페이징이 불가능하다.
-> order는 2개라 그걸 기준으로 페이징하고싶은데, data는 fetch join되면서 order item 수대로 4개가 된 상태 -> 그 상태로 페이징이 되어버림......(1:N이 아닌 경우에는 상관없음.)
하이버네이트는 경고 로그를 남기면서 모든 데이 터를 DB에서 읽어오고, 메모리에서 페이징 해버린다(매우 위험하다 -> 데이터가 많은 상황이라면?!!). 자세한 내용은 자바 ORM 표준 JPA 프로그래밍의 페치 조인 부분을 참고하자.
참고: 컬렉션 페치 조인은 1개만 사용할 수 있다. 컬렉션 둘 이상에 페치 조인을 사용하면 안된다. 데이터가 부정합하게 조회될 수 있다. 자세한 내용은 자바 ORM 표준 JPA 프로그래밍을 참고하자.
728x90
728x90
'프로그래밍 > spring boot' 카테고리의 다른 글
[스프링부트] 실전! 스프링 부트와 JPA 활용2 컬렉션 조회 최적화 #4 JPA에서 DTO 직접 조회 (1) | 2023.11.26 |
---|---|
[스프링부트] 실전! 스프링 부트와 JPA 활용2 컬렉션 조회 최적화 #3.1 페이징과 한계 돌파 (2) | 2023.11.26 |
[스프링부트] 실전! 스프링 부트와 JPA 활용2 컬렉션 조회 최적화 #2 엔티티를 DTO로 변환 (0) | 2023.11.26 |
[스프링부트] 실전! 스프링 부트와 JPA 활용2 컬렉션 조회 최적화 #1 엔티티 직접 노출 (2) | 2023.11.26 |
[스프링부트] 실전! 스프링 부트와 JPA 활용2 지연 로딩과 조회 성능 최적화 #1 간단한 주문 조회 V4: JPA에서 DTO로 바로 조회 (2) | 2023.11.25 |