JPA์์ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ํ๊ธฐ ์ํ ๋ช๊ฐ์ง ๋ฐฉ๋ฒ๋ค์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ชจ๋ ์ฐ๊ด๊ด๊ณ๋ ์ง์ฐ๋ก๋ฉ
๋ชจ๋ ์ฐ๊ด๊ด๊ณ๋ FetchType.LAZY๋ฅผ ํตํ ์ง์ฐ๋ก๋ฉ์ผ๋ก ์ค์ ํด ์ฃผ์๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
์ฆ์ ๋ก๋ฉ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์์ํ์ง ๋ชปํ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฉฐ, ์ด๋ ์ต์ ํ๋ฅผ ๋ฐฉํดํ๋ ์์๊ฐ ๋ฉ๋๋ค.
XToOne ๊ด๊ณ
ํ์น ์กฐ์ธ์ ์ฌ์ฉํฉ๋๋ค.
ToOne ๊ด๊ณ๋ฅผ ๋ชจ๋ ์ง์ฐ ๋ก๋ฉ์ผ๋ก ์ค์ ํ ์ดํ, ์กฐํํ๋ ์์ ์ ํ์น ์กฐ์ธ์ ํตํด ์กฐํํ๋ ๊ฒ์ผ๋ก ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
ToOne ๊ด๊ณ๋ ์กฐํ ์ row์๋ฅผ ์ฆ๊ฐ์ํค์ง ์๊ธฐ ๋๋ฌธ์, ์๋ฌด๋ฐ ๋ฌธ์ ์์ด ํ์ด์ง๋ ๊ฐ๋ฅํฉ๋๋ค.
์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋์๋ ์ํฐํฐ๋ก ์กฐํํ๋ ๋ฐฉ๋ฒ๊ณผ, DTO๋ก ๋ฐ๋ก ์กฐํํ๋ ๋ฐฉ๋ฒ์ ์ ํํ ์ ์์ต๋๋ค.
์ฑ๋ฅ์ ๊ทนํ์ผ๋ก ๋์ด์ฌ๋ฆฌ๋ ค๋ ๊ฒ์ด ์๋ ์ด์, ์ํฐํฐ๋ก ์กฐํํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
(ํ๋ฉด์ ์์กด์ ์ด์ง ์์ผ๋ฉฐ, ๋ฒ์ฉ์ ์ด๋ฉฐ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๊ธฐ๋ ํจ์ฌ ์ฝ์ต๋๋ค.)
์ํฐํฐ๋ก ์กฐํํ๋ ๋ฐฉ๋ฒ
em.createQuery("select o from Order o join fetch o.member m join fetch o.delivery d",
Order.class)
.getResultList();
DTO๋ก ์กฐํํ๋ ๋ฐฉ๋ฒ
em.createQuery(
"select new jpabook.jpashop.repository.OrderSimpleQueryDto(o.id, o.name, o.orderDate) " +
"from Order o "+
"join fetch o.member m "+
"join fetch o.delivery d",
OrderSimpleQueryDto.class)
.getResultList();
ํจํค์ง ๋ช ๊น์ง ๋ค ์ ์ด์ฃผ์ด์ผ ํฉ๋๋ค.
(์ฟผ๋ฆฌ DSL์ ์ฌ์ฉํ๋ฉด ์ข ๋ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.)
๊ฐ์ด๋
- ์ฐ์ ์ํฐํฐ๋ฅผ DTO๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ ํํฉ๋๋ค.
- ํ์ํ๋ฉด ํ์น ์กฐ์ธ์ผ๋ก ์ฑ๋ฅ์ ์ต์ ํ ํฉ๋๋ค. (๋๋ถ๋ถ์ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค.)
- ๊ทธ๋๋ ์ฑ๋ฅ ์ต์ ํ๊ฐ ํ์ํ๋ค๋ฉด DTO๋ก ์ง์ ์กฐํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํฉ๋๋ค.
- ์ตํ์ ๋ฐฉ๋ฒ์ผ๋ก๋ JPA๊ฐ ์ ๊ณตํ๋ ๋ค์ดํฐ๋ธ SQL์ด๋ ์คํ๋ง JDBC Template๋ฅผ ์ฌ์ฉํด์ SQL์ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
XToMany ๊ด๊ณ
ToOne ๊ด๊ณ๋ ํ์น ์กฐ์ธ์,
์ปฌ๋ ์ ์ default_batch_fetch_size(BatchSize)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
default_batch_fetch_size๋ ๊ธ๋ก๋ฒํ ์ค์ ์ด๋ฉฐ, @BatchSize๋ ์ํฐํฐ๋ณ๋ก ์ต์ ํ ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๊ธ๋ก๋ฒํ ์ค์ ๋ง์ผ๋ก ์ถฉ๋ถํฉ๋๋ค.
๋ฐฐ์น ์ฌ์ด์ฆ๊ฐ ์ด์ํ๊ฒ ์๋ํ๋ค๋ฉด
https://www.inflearn.com/questions/34469
์ปฌ๋ ์ ์ DTO๋ก ์กฐํํ๋ ๊ฒฝ์ฐ
์ปฌ๋ ์ ์ DTO๋ก ๋ฐ๋ก ์กฐํํ๋ ๊ฒ์ ๋ฐฐ์น์ฌ์ด์ฆ๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ ์ง์ IN ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ์ฌ ํด๊ฒฐํฉ๋๋ค.
public class OrderQueryDto {
private Long orderId;
private String name;
private Address address;
private List<OrderItemQueryDto> orderItems;
public OrderQueryDto(Long orderId, String name, Address address){
this.orderId = orderId;
this.name= name;
this.address= address;
}
}
public class OrderItemQueryDto {
private Long orderId;
private String itemName;
private int orderPrice;
private int count;
public OrderItemQueryDto(Long orderId, String itemName, int orderPrice, int count){
this.orderId = orderId;
this.itemName= itemName;
this.orderPrice= orderPrice;
this.count= count;
}
}
//findOrders()
em.createQuery(
"select new ~~~.OrderQueryDto(o.id, m.name, d.address)" +
" from Order o" +
" join o.member m" +
" join o.delivery d", OrderQueryDto.class).getResultList();
)
์ต์ ํ ์ ์ฉ ์
//findOrderItems()
em.createQuery(
"select .~~~.OrderItemQueryDto(oi.order.id,o.itemName, m.orderPrice, d.count)" +
" from OrderItem oi" +
" join oi.item i" +
" where oi.order.id =: orderId", OrderItemQueryDto.class)
.setParameter("orderId",orderId)
.getResultList();
)
List<OrderQueryDto> result = findOrders();
result.forEach(o -> {
List<OrderItemQueryDto> orderItems = findOrderItems(o.getOrderId());
o.setOrderItems(orderItems);
});
๋ฃจํธ๋ฅผ ์กฐํํ๋ ์ฟผ๋ฆฌ๋ 1๋ฒ, ์ปฌ๋ ์ ์ ์กฐํํ๋ ์ฟผ๋ฆฌ๋ N๋ฒ ์ํ๋์์ต๋๋ค. (N+1 ๋ฐ์)
์ต์ ํ ์ ์ฉ
//findOrderItems()
em.createQuery(
"select new japbook.~~~.OrderItemQueryDto(oi.order.id,o.itemName, m.orderPrice, d.count)" +
" from OrderItem oi" +
" join oi.item i" +
" where oi.order.id in :orderIds", OrderItemQueryDto.class) //In์ผ๋ก ๋ณ๊ฒฝ
.setParameter("orderIds",orderIds)
.getResultList();
)
List<OrderQueryDto> result = findOrders();//์ฟผ๋ฆฌ1๋ฒ
List<Long> orderIds = result.stream()
.map( o -> o.getOrderId())
.toList():
List<OrderItemQueryDto> orderItems = findOrderItems(orderIds);//์ฟผ๋ฆฌ1๋ฒ
Map<Long, List<OrderItemQueryDto>> orderItemMap = orderItems.stream()
.collect(Collectors.groupingBy(OrderItemQueryDto::getOrderId));
result.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));
์ฟผ๋ฆฌ๊ฐ ์ด 2๋ฒ์ด ๋ฐ์ํฉ๋๋ค.
์ ๋ฆฌ
์ํฐํฐ ์กฐํ ์
- ์ปฌ๋ ์ ์ ํ์น ์กฐ์ธ ์ ํ์ด์ง์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.
- ๋ฐ๋ผ์ ToOne๊ด๊ณ๋ ํ์น ์กฐ์ธ์ผ๋ก ์ฟผ๋ฆฌ ์๋ฅผ ์ต์ ํ ํฉ๋๋ค.
- ์ดํ ์ปฌ๋ ์ ์ ํ์น ์กฐ์ธ ๋์ ์ ์ง์ฐ ๋ก๋ฉ์ผ๋ก ์ ์ง ํ, default_batch_fetch_size ํน์ @BatchSize๋ก ์ต์ ํํฉ๋๋ค.
DTO ์ง์ ์กฐํ ์
- DTO๋ก ์กฐํ ์ ์ปฌ๋ ์ ์ IN์ ์ ํ์ฉํด์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฏธ๋ฆฌ ์กฐํํด์ ์ต์ ํํฉ๋๋ค.
๊ถ์ฅ ์์
- ์ํฐํฐ ์กฐํ ๋ฐฉ์์ผ๋ก ์ฐ์ ์ ๊ทผํฉ๋๋ค.
- ํ์น์กฐ์ธ์ผ๋ก ์ฟผ๋ฆฌ ์๋ฅผ ์ต์ ํํฉ๋๋ค
- ์ปฌ๋ ์
์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ค์์ ์ฌ์ฉํฉ๋๋ค.
- ํ์ด์ง ํ์ํ ๊ฒฝ์ฐ: ๋ฐฐ์น์ฌ์ด์ฆ ์ต์
- ํ์ด์ง์ด ํ์ ์๋ ๊ฒฝ์ฐ: ํ์น ์กฐ์ธ์ ์ฌ์ฉํฉ๋๋ค(๋จ 2๊ฐ ์ด์์ ์ฌ์ฉํ๋ฉด ์๋ฉ๋๋ค.)
- ์ํฐํฐ ์กฐํ ๋ฐฉ์์ผ๋ก ํด๊ฒฐ์ด ์๋๋ค๋ฉด DTO ์กฐํ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค.
- DTO ์กฐํ ๋ฐฉ์์ผ๋ก๋ ํด๊ฒฐ์ด ์๋๋ฉด NatviceSQL ๋๋ JdbcTemplate์ฌ์ฉํฉ๋๋ค.
๋ง๋ฌด๋ฆฌ
์์ ๋ฐฉ๋ฒ์ผ๋ก๋ ์ฑ๋ฅ์ด ์๋์จ๋ค๋ฉด ์บ์๋ฅผ ์ฌ์ฉํ๋๊ฐ ํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฐพ์์ผ ํฉ๋๋ค.
์์ผ๋ก ๊ณต๋ถํ ๋ด์ฉ์ด์ง๋ง, ์ํฐํฐ๋ ์ ๋ ์บ์๋ฅผ ํ๋ฉด ์๋ฉ๋๋ค.
์์์ฑ ์ปจํ ์คํธ์ ์บ์๊ฐ ์์ผ์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํฌ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์บ์๋ฅผ ํ ๋์๋ DTO๋ก ๋ณํํ์ฌ ์บ์๋ฅผ ํ์ฌ์ผ ํฉ๋๋ค.
(์ํฐํฐ๋ฅผ ์บ์ํ๋ 2์ฐจ์บ์๊ฐ ์๊ธด ํ์ง๋ง, ์ด๋ ์ค์ ๋ก ์ฌ์ฉํ๊ธฐ ๋๋ฌด ๊น๋ค๋กญ๋ค๊ณ ํฉ๋๋ค.)
Reference
'๐๏ธ Spring > JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPA] @OrderBy - ๋ฆฌ์คํธ์ ์์ ์ง์ ํ๊ธฐ (0) | 2021.12.21 |
---|---|
[JPA] OSIV ๋? (6) | 2021.12.20 |
[JPA] ๋ณํฉ(merge)์ ๋ํด (0) | 2021.12.18 |
[JPA] ์คํ๋ง๋ถํธ ์ฌ์ฉ ์ EntityManagerFactory๋ฅผ ์ฃผ์ ๋ฐ๋ ๋ฐฉ๋ฒ (@PersistenceUnit) (0) | 2021.12.18 |
[JPA] ์ํฐํฐ, ํ ์ด๋ธ, ์ปฌ๋ผ๋ช ์์ฑ ์ ๋ต (0) | 2021.12.18 |