ManyToOne最適化OneToOne関連クエリーV 3とV 4(最適)
5428 ワード
Order->デリバリはOneToOneに関連付けられ、Order->メンバーはManyToOneに関連付けられている場合、Orderに関連付けられたデリバリとメンバーもデータベースから値を取得し、応答として送信する操作です.
実際に処理されたクエリー文をチェックすることで、find Ordersをインポートした場合にのみクエリー文が処理されると判断できます.
応答として値を送信するとDTOも返されますが、DBにアクセスするとDTOを使用して必要な値も取得されます.(詳細はhttps://velog.io/@k_ms1998/JPA-JPQL-%ED%94%84%EB%A1%9C%EC%A0%9D%EC%85%98を参照)
DBアクセス時にJOIN FETCHとDTOを併用することはできないので、JOIN(INNER、OUTER)とDTOを使用します.
V 3とV 4のどちらが無条件に良いかは言い難い.もちろん、V 4はさらに最適化されていますが、クエリーの最適化時にColumnを追加してもパフォーマンスに大きな影響はありません.また、V 4は1つの仕様でのみ使用可能なので、繰り返し使用できません.逆に、V 3は、複数の仕様で繰り返し使用できるという利点がある.
そのため、状況に応じてV 3かV 4を使うべきだと思います.
V3: JOIN FETCH + DTO
API
@GetMapping("/api/v3/simple-orders")
public Result ordersV3() {
List<Order> findOrders = orderRepository.findALlWithOrderMember();
List<OrderDTO> orderDTOS = findOrders.stream()
.map(o -> new OrderDTO(o))
.collect(Collectors.toList());
return new Result(orderDTOS);
}
findAllWithOrderMember()
public List<Order> findALlWithOrderMember() {
String query = "select o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d";
return em.createQuery(query, Order.class)
.getResultList();
}
送信応答はV 2と同じDTOを返し,戻り値も同じである.ただし、findOrdersをインポートする場合も、JOIN FETCHをクエリー文として使用して関連関係のエンティティ値をインポートします.したがって、Order->OrderDTO変換では、DBにアクセスすることなく、メンバーと成果物の値をインポートできます.実際に処理されたクエリー文をチェックすることで、find Ordersをインポートした場合にのみクエリー文が処理されると判断できます.
/**
* 결과:
* (쿼리문:)
* 1. select order0_.order_id as order_id1_9_0_, member1_.member_id as member_i1_6_1_, delivery2_.delivery_id as delivery1_4_2_, order0_.member_id as member_i4_9_0_, order0_.order_date as order_da2_9_0_, order0_.status as status3_9_0_, member1_.city as city2_6_1_, member1_.street as street3_6_1_, member1_.zipcode as zipcode4_6_1_, member1_.username as username5_6_1_, delivery2_.city as city2_4_2_, delivery2_.street as street3_4_2_, delivery2_.zipcode as zipcode4_4_2_, delivery2_.order_id as order_id6_4_2_, delivery2_.status as status5_4_2_ from orders order0_
* inner join member member1_ on order0_.member_id=member1_.member_id
* inner join delivery delivery2_ on order0_.order_id=delivery2_.order_id
* => 총 1번의 쿼리문이 처리됨
*/
しかし,不要なColumnをすべて導入したため,これらの点では最適化の余地があり,V 4でこれについて議論する.V4: JOIN(DTO) + DTO
応答として値を送信するとDTOも返されますが、DBにアクセスするとDTOを使用して必要な値も取得されます.(詳細はhttps://velog.io/@k_ms1998/JPA-JPQL-%ED%94%84%EB%A1%9C%EC%A0%9D%EC%85%98を参照)
DBアクセス時にJOIN FETCHとDTOを併用することはできないので、JOIN(INNER、OUTER)とDTOを使用します.
API
@GetMapping("/api/v4/simple-orders")
public Result ordersV4() {
List<OrderQueryDTO> orderDTOS = orderRepository.findALlWithOrderMemberDTO();
return new Result(orderDTOS);
/**
* 결과:
* (쿼리문:)
* 1. select order0_.order_id as col_0_0_, member1_.username as col_1_0_, order0_.order_date as col_2_0_, order0_.status as col_3_0_, delivery2_.city as col_4_0_, delivery2_.street as col_4_1_, delivery2_.zipcode as col_4_2_ from orders order0_
* inner join member member1_ on order0_.member_id=member1_.member_id
* inner join delivery delivery2_ on order0_.order_id=delivery2_.order_id
* => 총 1번의 쿼리문이 처리됨 & V3이랑 비교 해봤을때 가져오는 Column이 다름
*
* 반환되는 Response는 V2&V3와 동일
*/
}
findALlWithOrderMemberDTO()
public List<OrderQueryDTO> findALlWithOrderMemberDTO() {
String query = "select new jpabook.jpashop.Repository.DTO.OrderQueryDTO(o.id, m.username, o.orderDate, o.status, d.address) from Order o" +
" join o.member m" +
" join o.delivery d";
return em.createQuery(query, OrderQueryDTO.class)
.getResultList();
}
OrderQueryDTO
@Data
public class OrderQueryDTO {
private Long orderId;
private String username; //주문자 이름
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address; //배송지
public OrderQueryDTO(Long orderId, String username, LocalDateTime orderDate, OrderStatus orderStatus, Address address) {
this.orderId = orderId;
this.username = username;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
this.address = address;
}
}
応答値は同じで、クエリー文も一度入力するだけで必要な値を得ることができ、実行されたクエリーを表示すると、インポートされたColumnがV 3と異なることがわかります.V3 vs. V4
V 3とV 4のどちらが無条件に良いかは言い難い.もちろん、V 4はさらに最適化されていますが、クエリーの最適化時にColumnを追加してもパフォーマンスに大きな影響はありません.また、V 4は1つの仕様でのみ使用可能なので、繰り返し使用できません.逆に、V 3は、複数の仕様で繰り返し使用できるという利点がある.
そのため、状況に応じてV 3かV 4を使うべきだと思います.
Reference
この問題について(ManyToOne最適化OneToOne関連クエリーV 3とV 4(最適)), 我々は、より多くの情報をここで見つけました https://velog.io/@k_ms1998/ManyToOne-OneToOne-연관관계-조회-최적화-V3V4Bestテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol