์ง์ฐ ๋ก๋ฉ๊ณผ ์ฑ๋ฅ ์ต์ ํ
์ฃผ๋ฌธ์กฐํ1: ์ํฐํฐ ์ง์ ๋ ธ์ถ
@GetMapping("/api/v1/simple-orders")
public List<Order> ordersV1() {
List<Order> all = orderRepository.findAllByString(new OrderSearch());
for (Order order : all) {
order.getMember().getName(); //Lazy ๊ฐ์ ์ด๊ธฐํ
order.getDelivery().getAddress(); //Lazy ๊ฐ์ ์ด๊ธฐํ
}
return all;
}
โ ์ํฐํฐ ์ง์ ๋ ธ์ถ ์ง์
โ order -> member
์ order -> address
๋ ์ง์ฐ ๋ก๋ฉ์ด๋ค. ๋ฐ๋ผ์ ์ค์ ์ํฐํฐ ๋์ ์ ํ๋ก์ ์กด์ฌ
โ ์๋ฐฉํฅ ๊ด๊ณ๋ @Jsonignore
์ค์ ์ ํด์ค๋ค.
- ์๋ก ํธ์ถํ๋ฉด์ ๋ฌดํ ๋ฃจํ
// Member.java
@Entity
@Getter @Setter
public class Member {
...
@JsonIgnore
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
ํ์ด๋ฒ๋ค์ดํธ ๋ชจ๋ ๋ฑ๋ก (spring 3.0 ๋ฏธ๋ง)
โ jackson
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ํ๋ก์ ๊ฐ์ฒด๋ฅผ json์ผ๋ก ์ด๋ป๊ฒ ์์ฑํด์ผ ํ๋์ง ๋ชจ๋ฆ ์์ธ ๋ฐ์
โ Hibernate5Module
์ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก
- build gradle์ ์์กด์ฑ ์ถ๊ฐ
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'
JpashopApplication
์ ๋ค์ ์ฝ๋๋ฅผ ์ถ๊ฐ@Bean Hibernate5Module hibernate5Module() { return new Hibernate5Module(); }
์ฃผ๋ฌธ์กฐํ 2: ์ํฐํฐ๋ฅผ DTO๋ก ๋ณํ
/**
* V2. ์ํฐํฐ๋ฅผ ์กฐํํด์ DTO๋ก ๋ณํ(fetch join ์ฌ์ฉX)
* - ๋จ์ : ์ง์ฐ๋ก๋ฉ์ผ๋ก ์ฟผ๋ฆฌ N๋ฒ ํธ์ถ
*/
@GetMapping("/api/v2/simple-orders")
public List<SimpleOrderDto> ordersV2() {
List<Order> orders = orderRepository.findAll();
List<SimpleOrderDto> result = orders.stream()
.map(o -> new SimpleOrderDto(o))
.collect(toList());
return result;
}
...
@Data
static class SimpleOrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //์ฃผ๋ฌธ์๊ฐ
private OrderStatus orderStatus;
private Address address;
public SimpleOrderDto(Order order) {
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
}
}
โ ์ํฐํฐ๋ฅผ DTO๋ก ๋ณํํ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ
โ ์ฟผ๋ฆฌ 1 + N + N๋ฒ ์คํ (N + 1 ๋ฌธ์ )
- order ์กฐํ 1๋ฒ
- order -> member ์ง์ฐ ๋ก๋ฉ ์กฐํ N ๋ฒ
- order -> delivery ์ง์ฐ ๋ก๋ฉ ์กฐํ N ๋ฒ
์ฃผ๋ฌธ์กฐํ3: ์ํฐํฐ๋ฅผ DTO๋ก ๋ณํ - ํ์น ์กฐ์ธ ์ต์ ํ
/**
* V3. ์ํฐํฐ๋ฅผ ์กฐํํด์ DTO๋ก ๋ณํ(fetch join ์ฌ์ฉO)
* - fetch join์ผ๋ก ์ฟผ๋ฆฌ 1๋ฒ ํธ์ถ
*/
@GetMapping("/api/v3/simple-orders")
public List<SimpleOrderDto> ordersV3() {
List<Order> orders = orderRepository.findAllWithMemberDelivery();
List<SimpleOrderDto> result = orders.stream()
.map(o -> new SimpleOrderDto(o))
.collect(toList());
return result;
}
// OrderRepository.java
public List<Order> findAllWithMemberDelivery() {
return em.createQuery(
"select o from Order o" +
" join fetch o.member m" +
" join fetch o.delivery d", Order.class)
.getResultList();
}
โ ์ํฐํฐ๋ฅผ ํ์น ์กฐ์ธ(fetch join)์ ์ฌ์ฉํด์ ์ฟผ๋ฆฌ 1๋ฒ์ ์กฐํ
โ ํ์น ์กฐ์ธ์ผ๋ก order -> member , order -> delivery ๋ ์ด๋ฏธ ์กฐํ ๋ ์ํ ์ด๋ฏ๋ก ์ง์ฐ๋ก๋ฉX
์ฃผ๋ฌธ์กฐํ 4: JPA์์ DTO๋ก ๋ฐ๋ก ์กฐํ
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4() {
return orderSimpleQueryRepository.findOrderDtos();
}
// OrderSimpleQueryRepository.java
package jpabook.jpashop.repository.order.simplequery;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class OrderSimpleQueryRepository {
private final EntityManager em;
public List<OrderSimpleQueryDto> findOrderDtos() {
return em.createQuery(
"select new jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address)" +
" from Order o" +
" join o.member m" +
" join o.delivery d", OrderSimpleQueryDto.class)
.getResultList();
}
}
// OrderSimpleQueryDto.java
package jpabook.jpashop.repository.order.simplequery;
import jpabook.jpashop.domain.Address;
import jpabook.jpashop.domain.OrderStatus;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class OrderSimpleQueryDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //์ฃผ๋ฌธ์๊ฐ
private OrderStatus orderStatus;
private Address address;
public OrderSimpleQueryDto(Long orderId, String name, LocalDateTime orderDate, OrderStatus orderStatus, Address address) {
this.orderId = orderId;
this.name = name;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
this.address = address;
}
}
โ ์ผ๋ฐ์ ์ธ SQL์ ์ฌ์ฉํ ๋์ฒ๋ผ ์ํ๋ ๊ฐ ์ ํํด์ ์กฐํ
โ new ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด์ JPQL์ ๊ฒฐ๊ณผ๋ฅผ DTO๋ก ์ฆ์ ๋ณํ
โ SELECT ์ ์์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ ํํ๋ฏ๋ก DB ์ ํ๋ฆฌ์ผ์ด์ ๋คํธ์ ์ฉ๋ ์ต์ ํ(์๊ฐ๋ณด๋ค ํฌ์ง ์๋ค)
โ ๋ฆฌํฌ์งํ ๋ฆฌ ์ฌ์ฌ์ฉ์ฑ ๋จ์ด์ง, API ์คํ์ ๋ง์ถ ์ฝ๋๊ฐ ๋ฆฌํฌ์งํ ๋ฆฌ์ ๋ค์ด๊ฐ๋ ๋จ์
์ ๋ฆฌ
โ ์ฟผ๋ฆฌ ๋ฐฉ์ ์ ํ ๊ถ์ฅ ์์
- ์ฐ์ ์ํฐํฐ๋ฅผ DTO๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ ํํ
- ํ์ํ๋ฉด ํ์น ์กฐ์ธ์ผ๋ก ์ฑ๋ฅ ์ต์ ํ. (๋๋ถ๋ถ์ ์ฑ๋ฅ ์ด์๊ฐ ํด๊ฒฐ๋จ)
- ๊ทธ๋๋ ์๋๋ฉด DTO๋ก ์ง์ ์กฐํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉ
- ์ตํ์ ๋ฐฉ๋ฒ์ JPA๊ฐ ์ ๊ณตํ๋ ๋ค์ดํฐ๋ธ SQL์ด๋ ์คํ๋ง JDBC Template์ ์ฌ์ฉํด์ SQL์ ์ง์ ์ฌ์ฉ
'โญ Personal_Study > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Java ๋ฌธ์์ด์์ ์ด๋ชจ์ง ์ ๊ฑฐํ๋ ๋ฒ (1) | 2023.03.31 |
---|---|
์งํฉ (Set) (1) | 2022.12.20 |
์์์งํฉ(Enum) (1) | 2022.12.19 |
๋งต(Map) (0) | 2022.12.18 |
๋ฐฐ์ด(Array) & ๋ฆฌ์คํธ(List) (0) | 2022.12.17 |
๋๊ธ