@Bean
Hibernate5Module hibernate5Module() {
Hibernate5Module hibernate5Module = new Hibernate5Module();
// hibernate5Module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true);
return hibernate5Module;
}
@GetMapping("/api/v1/orders")
public List<Order> getOrderV1() {
List<Order> all = orderRepository.findAllByString(new OrderSearch());
for (Order order : all) {
order.getMember().getName();
order.getDelivery().getAddress();
List<OrderItem> orderItems = order.getOrderItems();
orderItems.stream().forEach(o -> o.getItem().getName());
}
return all;
}
@GetMapping("/api/v2/orders")
public List<OrderDto> getOrderV2() {
List<Order> orders = orderRepository.findAllByString(new OrderSearch());
List<OrderDto> result = orders.stream()
.map(o -> new OrderDto(o))
.collect(Collectors.toList());
return result;
}
@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 order) {
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
orderItems = order.getOrderItems();
}
} -> OrderItems 가 엔티티라 더이상 조회 안됨.
order.getOrderItems().stream().forEach(o -> o.getItem().getName());
orderItems = order.getOrderItems(); 이렇게 바꾸면 Item도 조회 가능
# 엔티티가 DTO 내에서 노출됨
# DTO내의 엔티티도 다시 DTO 처리
@GetMapping("/api/v2/orders")
public List<OrderDto> getOrderV2() {
List<Order> orders = orderRepository.findAllByString(new OrderSearch());
List<OrderDto> result = orders.stream()
.map(o -> new OrderDto(o))
.collect(Collectors.toList());
return result;
}
@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 order) {
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
orderItems = order.getOrderItems().stream()
.map(orderItem -> new OrderItemDto(orderItem))
.collect(Collectors.toList());
}
}
@Getter
static class OrderItemDto {
private String itemName;
private int orderPrice;
private int count;
public OrderItemDto(OrderItem orderItem) {
itemName = orderItem.getItem().getName();
orderPrice = orderItem.getOrderPrice();
count = orderItem.getCount();
}
}
상품의 이름, 가격, 수량으로 딱 필요한 정보만 보기
1. 페이징 X
public List<Order> findAllWithItem() {
return em.createQuery(
"select distinct o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d" +
" join fetch o.orderItems oi" +
" join fetch oi.item i", Order.class
).getResultList();
}
# distinct
# DB에 distinct 키워드를 날려준다
# 엔티티가 중복인 경우에 중복 걸러서 컬렉션에 담아줌
@GetMapping("/api/v3/orders")
public List<OrderDto> getOrderV3() {
List<Order> orders = orderRepository.findAllWithItem();
List<OrderDto> result = orders.stream()
.map(o -> new OrderDto(o))
.collect(Collectors.toList());
return result;
}
# 어떤 Order를 가져오는지 궁금하다면
// for (Order order : orders) {
// System.out.println("order ref = " + order + " id = " +order.getId());
// }
2. 페이징 O
1. order,member,delivery는 페치조인 및 offset,limit 페이징(to One)
2. orderitems, item 은 지연로딩, in query로 size만큼 한번에 불러옴(to Many)
(hibernate.default_batch_fetch_size 설정, max : 1000)
1. application.yml 에 추가 - hibernate
default_batch_fetch_size: 100
2. controller
@GetMapping("/api/v3.1/orders")
public List<OrderDto> getOrderV3_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(Collectors.toList());
return result;
}
3. repository
public List<Order> findAllWithMemberDelivery(int offset, int limit) {
return em.createQuery(
"select o from Order o" +
" join fetch o.member" +
" join fetch o.delivery d", Order.class
) .setFirstResult(offset)
.setMaxResults(limit)
.getResultList();
}
> 총 3번의 쿼리 돔 (1 + 1 + 1)
> 페치조인 쿼리 - order, member, delivery
select
order0_.order_id as order_id1_6_0_,
member1_.member_id as member_i1_4_1_,
delivery2_.delivery_id as delivery1_2_2_,
order0_.delivery_id as delivery4_6_0_,
order0_.member_id as member_i5_6_0_,
order0_.order_date as order_da2_6_0_,
order0_.status as status3_6_0_,
member1_.city as city2_4_1_,
member1_.street as street3_4_1_,
member1_.zipcode as zipcode4_4_1_,
member1_.name as name5_4_1_,
delivery2_.city as city2_2_2_,
delivery2_.street as street3_2_2_,
delivery2_.zipcode as zipcode4_2_2_,
delivery2_.status as status5_2_2_
from
orders order0_
inner join
member member1_
on order0_.member_id=member1_.member_id
inner join
delivery delivery2_
on order0_.delivery_id=delivery2_.delivery_id limit ?
> select
orderitems0_.order_id as order_id5_5_1_,
orderitems0_.order_item_id as order_it1_5_1_,
orderitems0_.order_item_id as order_it1_5_0_,
orderitems0_.count as count2_5_0_,
orderitems0_.item_id as item_id4_5_0_,
orderitems0_.order_id as order_id5_5_0_,
orderitems0_.order_price as order_pr3_5_0_
from
order_item orderitems0_
where
orderitems0_.order_id in ( // in 쿼리
?, ?
)
: binding parameter [1] as [BIGINT] - [4]
: binding parameter [2] as [BIGINT] - [11] // [4,11]로 한번에
// limit : 100, 100개까지 한꺼번에 in 쿼리로 가져옴
> select
item0_.item_id as item_id2_3_0_,
item0_.name as name3_3_0_,
item0_.price as price4_3_0_,
item0_.stock_quantity as stock_qu5_3_0_,
item0_.artist as artist6_3_0_,
item0_.etc as etc7_3_0_,
item0_.author as author8_3_0_,
item0_.isbn as isbn9_3_0_,
item0_.actor as actor10_3_0_,
item0_.director as directo11_3_0_,
item0_.dtype as dtype1_3_0_
from
item item0_
where
item0_.item_id in ( // in 쿼리
?, ?, ?, ?
)
: binding parameter [1] as [BIGINT] - [2]
: binding parameter [2] as [BIGINT] - [3]
: binding parameter [3] as [BIGINT] - [9]
: binding parameter [4] as [BIGINT] - [10] // [2, 3, 9, 10]