반응형
Entity를 Dto로 감싸라
body에 실려서 클라이언트와 통신하는 데이터들은 외부에 노출되면 안된다.
따라서 Db와 연결되는 Entity를 Dto감싸야된다.
@Getter
static class OrderDto{
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
private List<OrderItem> orderItems;
public OrderDto(Order o){
this.orderId = o.getId();
this.name = o.getMember().getName();
this.orderDate = o.getOrderDate();
this.orderStatus = o.getStatus();
this.address = o.getDelivery().getAddress();
this.orderItems = o.getOrderItems();
}
}
와 같은 코드가 있을때 마지막 orderItems의 타입인 OrderItem도 엔티티이기 때문에 꼭! OrderItem도 dto로 변환해야 한다.
따라서 아래처럼 OrderItemDTO를 추가작성해야한다
@Getter
static class OrderDto{
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
private List<OrderItemDto> orderItems;
public OrderDto(Order o){
this.orderId = o.getId();
this.name = o.getMember().getName();
this.orderDate = o.getOrderDate();
this.orderStatus = o.getStatus();
this.address = o.getDelivery().getAddress();
this.orderItems = o.getOrderItems().stream()
.map(OrderItemDto::new)
.collect(Collectors.toList());
}
}
@Getter
static class OrderItemDto{
private String itemName;
private int orderPrice;
private int count;
public OrderItemDto(OrderItem oi){
itemName = oi.getItem().getName();
orderPrice = oi.getOrderPrice();
count = oi.getCount();
}
}
이렇게 클라이언트와 통신하기위한 Dto를 사용하면 orderitem정보에 원하는 데이터만 담기게된다.
그렇다면 쿼리를 사용해서 어떻게 가져와야할까?
N+1 문제를 해결하기위해 fetch join을 사용하면 된다.
이때 약간의 팁을 주자면 distinct를 사용하여 증가된 row( 조회 쿼리도 증가)를 감소 시킬 수 있다.
하지만 페이징이 불가능하게 된다.
!! 컬렉션 패치 조인을 사요ㅕㅇ하면 페이징 안된다. 하이버네이트는 경고 로그를 남기면서 모든 데이터를 DB에서 읽어오고 메모리에서 페이징 해버린다(위험)
페이징을 가능하게 하기위해선?
컬렉션을 패치조인하면 페이징이 불가능하다
- 컬렉션을 패치조인하면 일대다 조인이 발생하므로 데이터를 예측할 수 없다.
- 일대다에서 일을 기준으로 페이징하는것이 목적이지만 데이터는 N을 기준으로 row가 생성된다.
- Order를 기준으로 페이징 하고 싶은데 N인 OrderItem을 조인하면 OrderItem이 기준이 되어버린다.
ToOne관께를 모두 패치조인한다. ToOne 관계는 row 수를 증가싴지 않으므로 페이징 쿼리에 영항을 미치지 않는다
컬렉션은 지연 로딩으로 조회한다.
지연 로딩 성능 최적화를 위해 hibernate.default_batch_fetch_size
, @BatchSize
를 적용한다.
- hibernate.default_batch_fetch_size: 글로벌 설정
- @BatchSize : 개별 최적화
- 이 옵션을 사용하면 컬렉션, 프록시 객체를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회한다.
반응형
'Java' 카테고리의 다른 글
[JPA] 중급 JPQL (0) | 2022.05.18 |
---|---|
[JPA]JPQL (0) | 2022.05.11 |
[JPA] 값타입 (0) | 2022.05.03 |
[JPA] 상속관계 매핑 (1) | 2022.04.10 |
[JPA] Proxy, 즉시로딩, 지연로딩 (0) | 2022.04.01 |