Hibernate5Module 모듈 등록, LAZY=null 처리
양방향 관계 문제 발생 -> @JsonIgnore
< SQL 실행 수 >
1. order 1번
2. member , address N번(order 조회 수 만큼)
3. orderItem N번(order 조회 수 만큼)
4. item N번(orderItem 조회 수 만큼)
지연 로딩 은 영속성 컨텍스트에 있으면 영속성 컨텍스트에 있는 엔티티를 사용하고 없으면 SQL을 실행한다.
따라서 같은 영속성 컨텍스트에서 이미 로딩한 회원 엔티티를 추가로 조회하면 SQL을 실행하지 않는다.
@GetMapping("/api/v3/orders")
public List<OrderDto> ordersV3() {
List<Order> orders = orderRepository.findAllWithItem();
List<OrderDto> result = orders.stream()
.map(o -> new OrderDto(o))
.collect(toList());
return result;
}
distinct 사용한 이유
1대다 조인이 있으므로 데이터베이스 row(열)증가 -> 같은 order 엔티티의 조회 수도 증가하게 된다.
JPA의 distinct는 SQL에 distinct를 추가하고, 같은 엔티티가 조회되면 애플리케이션에서 중복을 걸러준다.
=> order가 컬렉션 페치 조인때문에 중복 조회되는 것 방지
@GetMapping("/api/v3.1/orders")
public List<OrderDto> ordersV3_page(@RequestParam(value = "offset", defaultValue = "0")
int offset, @RequestParam(value = "limit", defaultValue = "100") int limit) {
List<Order> orders = orderRepository.findAllWithMemberDelivery(offset, limit);
List<OrderDto> result = orders.stream()
.map(o -> new OrderDto(o))
.collect(toList());
return result;
}
[ 장점 ]
1. 쿼리 호출 수가 1+N -> 1+1로 최적화
2 .조인보다 DB데이터 전송량이 최적화됨
3. 페치 조인 방식과 비교해서 쿼리 호출 수가 약간 증가하지만 DB 데이터 전송량 감소
4. 컬렉션 페치 조인은 페이징이 불가능하지만 이 방법은 페이징 가능
ToOne 관계는 페치 조인해도 페이징에 영향을 주지 않는다.
따라서 ToOne 관계는 페치 조인으로 쿼리 수를 줄이고,
나머지는hibernate.default_batch_fetch_size
로 최적화
hibernate.default_batch_fetch_size
, @BatchSize
엔티티 조회 방식 vs DTO 직접 조회하는 방식
엔티티 조회 = 페치 조인이나,
hibernate.default_batch_fetch_size
,@BatchSize
같이 코드를 거의 수정하지 않고, 옵션만 약간 변경해서, 다양한 성능 최적화를 시도할 수 있다.
DTO 조회 = 성능을 최적화 하거나 성능 최적화 방식을 변경할 때 많은 코드를 변경해야 한다.