์ปฌ๋ ์ ์กฐํ ์ต์ ํ - 1 ์์๋ ์ํฐํฐ๋ฅผ ์กฐํํ ํ์ DTO๋ก ๋ณํ์ํค๋ ๋ฐฉ์์ผ๋ก ํ์์ง๋ง,
์ด๋ฒ ์ฑํฐ์์๋ JPA ์์ DTO๋ฅผ ์ง์ ์กฐํํ๋ ๋ฐฉ์์ผ๋ก ์งํํ๋ค.
JPA์์ DTO ์ง์ ์กฐํ
DTO๋ฅผ ์กฐํํ ๋, ToOne ๊ด๊ณ๋ค์ ๋จผ์ ์กฐํํ๊ณ ToMany ๊ด๊ณ๋ค์ ๋ณ๋๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด ์ข๋ค.ToOne ๊ด๊ณ๋ฅผ ๋จผ์ ์ฒ๋ฆฌํ๋ ์ด์ ๋ Row ์์ ์ํฅ์ ์ฃผ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.ํ์ง๋ง ToMany ๊ด๊ณ๋ Row์๋ฅผ ์ฆ๊ฐ์ํค๋ฏ๋ก(๋ฐ์ดํฐ ๋ปฅํ๊ธฐ) ๋ณ๋๋ก ์ฒ๋ฆฌํ๋ ํธ์ด ์ข๋ค.
private List<OrderQueryDto> findOrders() {return em.createQuery(
"select new
jpabook.jpashop.repository.order.query.OrderQueryDto(o.id, m.name, o.orderDate,
o.status, d.address)" +
" from Order o" +
" join o.member m" +
" join o.delivery d", OrderQueryDto.class)
.getResultList();
}
/**
* 1:N ๊ด๊ณ์ธ orderItems ์กฐํ
*/
private List<OrderItemQueryDto> findOrderItems(Long orderId) {
return em.createQuery(
"select new
jpabook.jpashop.repository.order.query.OrderItemQueryDto(oi.order.id, i.name,
oi.orderPrice, oi.count)" +
" from OrderItem oi" +
" join oi.item i" +
" where oi.order.id = : orderId",
OrderItemQueryDto.class)
.setParameter("orderId", orderId)
.getResultList();
}
์์ ์ฝ๋์์ findOrder() ๋ฉ์๋๋ฅผ ํตํด ์ฃผ๋ฌธ๋ค์ ๋ชจ๋ ์กฐํํ๋ค.
์ฃผ๋ฌธ๋ค์ ๋ชจ๋ ์กฐํํ๋ ์ด์ ๋ ์ํฐํฐ์ ์ฃผ๋ฌธ์ ToOne ๊ด๊ณ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
์ฃผ๋ฌธ ์์ดํ ๋ค์ ๋ณ๋๋ก ์ฒ๋ฆฌํด์ฃผ์๋ ๋ฐ ์ด ์ญ์ ์์์ ์ค๋ช ํ๋๋ก ToMany ๊ด๊ณ์ด๊ธฐ ๋๋ฌธ์ ๋ณ๋๋ก ์ฒ๋ฆฌํ์๋ค.
public List<OrderQueryDto> findOrderQueryDtos() {
//๋ฃจํธ ์กฐํ(toOne ์ฝ๋๋ฅผ ๋ชจ๋ ํ๋ฒ์ ์กฐํ)
List<OrderQueryDto> result = findOrders();
//๋ฃจํ๋ฅผ ๋๋ฉด์ ์ปฌ๋ ์
์ถ๊ฐ(์ถ๊ฐ ์ฟผ๋ฆฌ ์คํ)
result.forEach(o -> {
List<OrderItemQueryDto> orderItems =
findOrderItems(o.getOrderId());
o.setOrderItems(orderItems);
});
ret
์ด๋ ๊ฒ ์กฐํ๋ ๊ฒฐ๊ณผ๋ค์ DTO์ ๋งคํ์์ผฐ๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ ํ๋ฉด, id ๋ฅผ ์กฐํํ ๋ ์ฟผ๋ฆฌ 1๋ฒ์ด ๋ฐ์ํ๊ณ ๊ทธ ๋ค๋ก ์ปฌ๋ ์ ์ ์กฐํํ ๋ ์ฟผ๋ฆฌ N๋ฒ์ด ๋ฐ์ํ๋ฏ๋ก
1+N ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
๋ฐ๋ผ์ ์ต์ ํ๊ฐ ํ์ํ๋ค.
JPA์์ DTO ์ง์ ์กฐํ - ์ปฌ๋ ์ ์กฐํ ์ต์ ํ
๊ธฐ์กด์ ๋ฃจํ๋ฅผ ๋๋ฉด์ ์กฐํํ๋ ๋ฐฉ์์ Map ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ด์ฉํจ์ผ๋ก์จ 1+N ๋ฌธ์ ๋ฅผ ๊ฐ์ ํ ์ ์๋ค.
private Map<Long, List<OrderItemQueryDto>> findOrderItemMap(List<Long>
orderIds) {
List<OrderItemQueryDto> orderItems = em.createQuery(
"select new
jpabook.jpashop.repository.order.query.OrderItemQueryDto(oi.order.id, i.name,
oi.orderPrice, oi.count)" +
" from OrderItem oi" +
" join oi.item i" +
" where oi.order.id in :orderIds", OrderItemQueryDto.class)
.setParameter("orderIds", orderIds)
.getResultList();
return orderItems.stream()
.collect(Collectors.groupingBy(OrderItemQueryDto::getOrderId));
}
๊ธฐ์กด ์ฝ๋์ ๋ค๋ฅธ ์ ์ ํ๋ผ๋ฏธํฐ๋ก ์ฃผ๋ฌธId (์๋ณ์) ๊ฐ ๋ด๊ธด ๋ฆฌ์คํธ๋ฅผ ๋๊ฒจ์คฌ๋ค๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ํจ์ผ๋ก์จ ๊ธฐ์กด ๋ฃจํ ์ฟผ๋ฆฌ๊ฐ ์๋ in์ฟผ๋ฆฌ๋ฅผ ํตํด ์์ดํ ์ ๋ณด๊ฐ ๋ด๊ธด ๋ฐ์ดํฐ๋ค์ ํ๋ฒ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ฒ ๋ถ๋ฌ์จ ๋ฐ์ดํฐ๋ค์ Map ์ ์ด์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌํ๋ค.
result.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));
๋ง์ง๋ง์ผ๋ก DTO ์ ๋งคํ์ํฌ ๋, ์ด๋ฏธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌ๋์๋ ์ํ์ด๋ฏ๋ก ์ถ๊ฐ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
์ด๋ ๊ฒ ํจ์ผ๋ก์จ ๋ฃจํธ ์ฟผ๋ฆฌ์์ 1๋ฒ , ์ปฌ๋ ์ ์กฐํํ ๋ 1๋ฒ๋ง ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ฏ๋ก 1+N ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
JPA์์ DTO๋ก ์ง์ ์กฐํ, ํ๋ซ ๋ฐ์ดํฐ ์ต์ ํ
์ฟผ๋ฆฌ๋ฅผ ํ๋ฒ๋ง ๋ ๋ ค์ ํ์ํ ๋ฐ์ดํฐ๋ค์ ๋ชจ๋ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ผ๋ก , ์์๋ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ด๋ค.
public List<OrderFlatDto> findAllByDto_flat() {
return em.createQuery(
"select new
jpabook.jpashop.repository.order.query.OrderFlatDto(o.id, m.name, o.orderDate,
o.status, d.address, i.name, oi.orderPrice, oi.count)" +
" from Order o" +
" join o.member m" +
" join o.delivery d" +
" join o.orderItems oi" +
" join oi.item i", OrderFlatDto.class)
.getResultList();
}
๋จผ์ ์กฐํํ ๋ฐ์ดํฐ๋ค์ "๋ชจ๋" ๊ฐ์ ธ์จ๋ค.
public List<OrderQueryDto> ordersV6() {
List<OrderFlatDto> flats = orderQueryRepository.findAllByDto_flat();
return flats.stream()
.collect(groupingBy(o -> new OrderQueryDto(o.getOrderId(),
o.getName(), o.getOrderDate(), o.getOrderStatus(), o.getAddress()),
mapping(o -> new OrderItemQueryDto(o.getOrderId(),
o.getItemName(), o.getOrderPrice(), o.getCount()), toList())
)).entrySet().stream()
.map(e -> new OrderQueryDto(e.getKey().getOrderId(),
e.getKey().getName(), e.getKey().getOrderDate(), e.getKey().getOrderStatus(),
e.getKey().getAddress(), e.getValue()))
.collect(toList());
}
๊ทธ ๋ค์ ์ด์ฒ๋ผ ์ดํ๋ฆฌ์ผ์ด์ ๋จ๊ณ์์ API ์คํ์ ๋ง๊ฒ ์ถ๊ฐ ์์ ์ ํด์ฃผ์ด์ผํ๋ค.
๋ณด๊ธฐ๋ง ํด๋ ์ด์ง๋ฝ๋ค ..
์ด ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง ๋จ์ ์ด ์๋ค.
1. ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํํฐ๋ง ์์ด ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์ ์ค๋ณต ๋ฐ์ดํฐ๊ฐ ๋ฐ์ํ๋ค.
์ค๋ณต ๋ฐ์ดํฐ๊น์ง ํจ๊ป ๊ฐ์ ธ์ค๋ฏ๋ก ์ฟผ๋ฆฌ๋ ์ค์์ง๋ง ์คํ๋ ค ์ฑ๋ฅ์ ์ ํ๋ ์ ์๋ค..
2. ์ดํ๋ฆฌ์ผ์ด์ ๋จ๊ณ์์ ์ถ๊ฐ ์์ ์ ํด์ค์ผํ๋ค.
3. ํ์ด์ง์ด ์๋๋ค!
์ฃผ๋ฌธ ํ๋(1)๋น ์ฌ๋ฌ๊ฐ(N)์ ๋ฐ์ดํฐ๋ค์ด ๋ธ๋ ค์ค๋๋ฐ ์ฌ๊ธฐ์ ํ์ด์ง์ ํ๋ฉด (N)์ ๊ธฐ์ค์ผ๋ก ํ์ด์ง์ด ๋๋ค.
'jpa' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[jpa] OSIV ์ฑ๋ฅ ์ต์ ํ (0) | 2023.03.05 |
---|---|
[jpa] ์ปฌ๋ ์ ์กฐํ ์ต์ ํ - 1 (0) | 2023.02.27 |
[jpa] ์ง์ฐ๋ก๋ฉ๊ณผ ์กฐํ ์ฑ๋ฅ ์ต์ ํ (0) | 2023.02.25 |
[jpa] ๋ค์ํ ์ฐ๊ด๊ด๊ณ ๋งตํ ์ ๋ฆฌ (0) | 2023.02.19 |
์์๊ด๊ณ ๋งคํ ์ ๋ต ์ข ๋ฅ ๋ฐ ์ ํ๊ฐ์ด๋ (0) | 2022.02.27 |