인프런 커뮤니티 질문&답변
v2 api의 delivery 쿼리 조회문
해결된 질문
작성
·
313
3
안녕하세요 영한님! 간단한 주문 조회v2 질문이 있습니다.
@GetMapping("/api/v2/simple-orders")
public Result ordersV2() {
List<Order> orders = orderService.findAll(new OrderSearch());//프록시가 들어있는 orde 객체
List<SimpleOrderDto> collect = orders.stream().map(o -> new SimpleOrderDto(o.getId(), o.getMember().getName(),
o.getOrderDate(), o.getStatus(), o.getDelivery().getAddress())).
collect(Collectors.toList());
return new Result(collect);
}
위의 v2 api를 실행하면 문제없이 5개의 쿼리문이 나가는 것을 확인했습니다.
name을 조회하는 쿼리는 예상했던데로 단순 조회 쿼리인
select
member0_.member_id as member_i1_5_0_,
member0_.city as city2_5_0_,
member0_.street as street3_5_0_,
member0_.zipcode as zipcode4_5_0_,
member0_.name as name5_5_0_
from
member member0_
where
member0_.member_id=?
와 같이 나가지만.
delivery 엔티티에 접근할때
select
delivery0_.delivery_id as delivery1_2_0_,
delivery0_.city as city2_2_0_,
delivery0_.street as street3_2_0_,
delivery0_.zipcode as zipcode4_2_0_,
delivery0_.status as status5_2_0_,
order1_.orders_id as orders_i1_6_1_,
order1_.delivery_id as delivery4_6_1_,
order1_.member_id as member_i5_6_1_,
order1_.order_date as order_da2_6_1_,
order1_.status as status3_6_1_
from
delivery delivery0_
left outer join
orders order1_
on delivery0_.delivery_id=order1_.delivery_id
where
delivery0_.delivery_id=?
위와 같이 외부 조인문이 나가는 것을 확인했습니다. 마치 패치조인을 한거 같은 전혀 예상치 못한 쿼리문이여서 질문을 드립니다. 또한 모두 lazy로 설정을 했습니다.
혹시 데이터베이스의 방언차이 때문일까요? mysql 사용중입니다.
퀴즈
JPA 엔티티를 API 응답으로 직접 노출할 때 발생할 수 있는 주요 문제는 무엇일까요?
데이터 손실
무한 루프 발생
DB 연결 오류
메모리 누수
답변 4
1
1
안녕하세요. 상운님^^
JPA에서 @OneToOne 관계에서는 기능의 한계로 본인이 FK를 가지고 있지 않은 이상, 항상 즉시로딩으로 동작합니다.
다음 강의를 참고해주세요.
추가로 @OneToOne 관계에서 한계에 대한 더 자세한 대응 방안은 다음 질문을 참고해주세요
https://www.inflearn.com/questions/40670
https://www.inflearn.com/questions/224187
감사합니다.
1
0
확인 해보니 상품 엔티티도 외부조인이 발생합니다..ㅠ
주문 엔티티
@Entity
@Getter @Setter
@Table(name = "orders")
public class Order {
@Id @GeneratedValue
@Column(name = "orders_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "delivery_id")
private Delivery delivery;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
/**
*
* 연관 관계 편의 메서드
*/
public void setMember(Member member) {
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem) {
this.orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery() {
this.delivery = delivery;
delivery.setOrder(this);
}
/**
* 생성 메서드
*/
public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItem) {
Order order = new Order();
order.setMember(member);
order.setDelivery(delivery);
for (OrderItem item : orderItem) {
order.addOrderItem(item);
}
order.setOrderDate(LocalDateTime.now());
order.setStatus(OrderStatus.ORDER);
return order;
}
/**
* 취소 메소드
*/
public int getSum() {
int sum = 0;
for (OrderItem orderItem : this.orderItems) {
sum += orderItem.totalPrice();
}
return sum;
}
public void cancel() {
if (this.delivery.getStatus() == DeliveryStatus.COMP) {
throw new IllegalStateException("이미 배송이 완료됬습니다.");
}
setStatus(OrderStatus.CANCEL);
for (OrderItem orderItem : this.orderItems) {
orderItem.cancel();
}
}
}
배송 엔티티
@Entity
@Getter @Setter
public class Delivery {
@Id @GeneratedValue
@Column(name = "delivery_id")
private Long id;
@JsonIgnore
@OneToOne(mappedBy = "delivery")
private Order order;
@Embedded
private Address address;
@Enumerated(EnumType.STRING)
private DeliveryStatus status;
}
상품 엔티티
@Service
@RequiredArgsConstructor
@Transactional
public class ItemService {
private final ItemRepository itemRepository;
public Long join(Item item) {
itemRepository.saveItem(item);
return item.getId();
}
public Item findOne(Long itemId) {
return itemRepository.findItem(itemId);
}
public List<Item> findAll() {
return itemRepository.findItems();
}
@Transactional
public void edit(ItemForm itemForm) {
Book book = (Book)findOne(itemForm.getId());
book.setName(itemForm.getName());
book.setPrice(itemForm.getPrice());
book.setStockQuantity(itemForm.getStockQuantity());
book.setAuthor(itemForm.getAuthor());
book.setIsbn(itemForm.getIsbn());
}
}





