해결된 질문
작성
·
243
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 사용중입니다.
답변 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());
}
}