인프런 커뮤니티 질문&답변

김상운님의 프로필 이미지
김상운

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

간단한 주문 조회 V3: 엔티티를 DTO로 변환 - 페치 조인 최적화

v2 api의 delivery 쿼리 조회문

해결된 질문

작성

·

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를 가지고 있지 않은 이상, 항상 즉시로딩으로 동작합니다.

다음 강의를 참고해주세요.

JPA 기본편 -> 일대일[1:1]

추가로 @OneToOne 관계에서 한계에 대한 더 자세한 대응 방안은 다음 질문을 참고해주세요

https://www.inflearn.com/questions/40670

https://www.inflearn.com/questions/224187

감사합니다.

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 상운님

작성하신 Order, Delivery 엔티티 코드를 모두 보여주시겠어요?

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());
}
}
김상운님의 프로필 이미지
김상운

작성한 질문수

질문하기