• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

주문 조회 v2에서 에러가 발생 & 궁금한 점이 있습니다

22.09.19 19:55 작성 조회수 384

0

안녕하세요.

주문 조회 V2("api/v2/orders")에서 코드를 작성하고 포스트맨을 실행시켰는데 에러가 발생합니다.

datatype jackson hibernate5 모듈은 설치하지 않았습니다.

@Entity
@Table(name = "orders") // 관례
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {

    @Id @GeneratedValue
    @Column(name = "order_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; // 주문 상태 [ORDER, CANCEL]
}
@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {

    @Id
    @GeneratedValue
    @Column(name = "order_item_id")
    private Long id;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "item_id")
    private Item item;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")
    private Order order;

    private int OrderPrice; // 주문 가격
    private int count; // 주문 수량
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype")
@Getter @Setter
public class Item {

    @Id
    @GeneratedValue
    @Column(name = "item_id")
    private Long id;

    private String name;
    private int price;
    private int stockQuantity;

    @ManyToMany(mappedBy = "items")
    private List<Category> categories = new ArrayList<>();
}
@RestController
@RequiredArgsConstructor
public class OrderApiController {

    private final OrderRepository orderRepository;

    @GetMapping("/api/v2/orders")
    public List<OrderDto> orderV2() {
        List<Order> orders = orderRepository.findAllByString(new OrderSearch());
        List<OrderDto> collect = orders.stream()
                .map(o -> new OrderDto(o))
                .collect(Collectors.toList());
        return collect;
    }

    @Data
    static class OrderDto {
        private Long orderId;
        private String name;
        private LocalDateTime orderDate;
        private OrderStatus orderStatus;
        private Address address;
        private List<OrderItem> orderItems;

        public OrderDto(Order order) {
            orderId = order.getId();
            name = order.getMember().getName();
            orderDate = order.getOrderDate();
            orderStatus = order.getStatus();
            address = order.getDelivery().getAddress();
            // order.getOrderItems().stream().forEach(o -> o.getItem().getName()); // 프록시 초기화
            orderItems = order.getOrderItems();
        }
    }
}

포스트맨 실행시, 결과가 아래처럼 출력됩니다.

[
    {
        "orderId": 4,
        "name": "userA",
        "orderDate": "2022-09-19T19:28:18.294267",
        "orderStatus": "ORDER",
        "address": {
            "city": "서울",
            "street": "1",
            "zipcode": "1111"
        },
        "orderItems": [
            {
                "id": 6,
                "count": 1,
                "orderPrice": 10000,
                "totalPrice": 10000
            },
            {
                "id": 7,
                "count": 2,
                "orderPrice": 20000,
                "totalPrice": 40000
            }
        ]
    },
    {
        "orderId": 11,
        "name": "userB",
        "orderDate": "2022-09-19T19:28:18.333162",
        "orderStatus": "ORDER",
        "address": {
            "city": "부산",
            "street": "2",
            "zipcode": "2222"
        },
        "orderItems": [
            {
                "id": 13,
                "count": 3,
                "orderPrice": 20000,
                "totalPrice": 60000
            },
            {
                "id": 14,
                "count": 4,
                "orderPrice": 40000,
                "totalPrice": 160000
            }
        ]
    }
  • order.getOrderItems().stream().forEach(o -> o.getItem().getName());를 프록시를 초기화시키는 부분이라고 이해했는데, 해당 부분을 주석처리하거나 안하거나 결과가 똑같이 출력됩니다. 이유를 모르겠는데, 어디선가 프록시가 초기화가 된걸까요..?

    • orderItem 값 자체가 아니라 프록시 객체를 초기화하는게 맞..죠..ㅠㅠ?!

  • 그리고 강의와 다르게 item에 대한 정보가 출력되지 않는데, 혹시 datatype jackson hibernate5 모듈을 설치하지 않았기 때문에 발생하는 문제인가요? ('간단한 주문 조회 V2'에서는 강의와 똑같이 출력되었어서 문제가 뭔지 모르겠습니다.)

     

  • 또, OrderItem.item@JsonIgnore을 추가하지 않을 때 아래와 같은 에러가 발생하는데, 지연 로딩에 의한 에러가 맞나요? (OrderItemItem 엔티티가 양방향 매핑이 아닌데.. '간단한 주문조회 V1' 강의에서 양방향 매핑에서 발생했던 에러 메세지와 비슷해보여서 질문드리게 되었습니다.)

  • 지연 로딩이 맞다면, order.getOrderItems().stream().forEach(o -> o.getItem().getName());에서 o.getItem().getName()에 의해 item에 대한 쿼리를 날리게 되어 이 부분이 해결되지 않나 싶은데 제가 틀리게 이해한건가요ㅠㅠ?

    com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->jpabook.jpashop.API.OrderApiController$OrderDto["orderItems"]->org.hibernate.collection.internal.PersistentBag[0]->jpabook.jpashop.Domain.OrderItem["item"]->jpabook.jpashop.Domain.Item.Item$HibernateProxy$Hp0g9cdN["hibernateLazyInitializer"])

    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.13.3.jar:2.13.3]

    • 에러를 해결할 수 있는 방법도 궁금합니다.

     

  • OrderDto에서 items를 따로 추가해 order.getOrderItems().getItem()들을 출력해보려고 했는데 방법이 틀린건가요? (위에 forEach문을 보면 해당 방법을 통한 접근이 가능한 것 같아서 시도해봤습니다..!)

답변 1

답변을 작성해보세요.

0

안녕하세요. 송유진님

전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

추가로 다음 내용도 코멘트 부탁드립니다.

1. 실행 방법을 알려주세요.

2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.

감사합니다.