스프링데이터 + JPA/API 개발

7. 엔티티를 Dto로

sdafdq 2023. 11. 13. 17:32
@GetMapping("/api/v2/simple-orders")
public List<SimpleOrderDto> ordersV2(){
    List<Order> orders = orderRepository.findAllString(new OrderSearch());

    List<SimpleOrderDto> result = orders.stream()
            .map(o -> new SimpleOrderDto(o))
            .collect(Collectors.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){ //별로 중요하지 않는 곳에서 엔티티를 의존하는 것이기 때문에 Dto에서 엔티티 생성자 정도는 괜찮다.
        this.orderId = order.getId();
        this.name = order.getMember().getName();
        this.orderDate = order.getOrderDate();
        this.orderStatus = order.getStatus();
        this.address = order.getDelivery().getAddress();
    }
}

엔티티 말고 이제 Dto로 따로 만들어서 주게끔 했다.

이제 엔티티에서 뭔가 변경되어도 바로 컴파일 오류로 잡아줄 것이고, api 스펙도 딱 정할 수 있다.

 

먼저 Order들을 찾아와서, Dto로 바꾼다.

 

Dto 생성자에서 엔티티를 받아 파싱하는 건 별로 중요하지 않는 곳에서 엔티티를 의존하는 것이기 때문에 괜찮다고 했다.

나는 저거 자주 이용할 거 같다.

확실히 그냥 값을 받아오기만 하는 거니까.

근데 이번에는 주는 객체 같은 것들도 임베디드 타입이고, 원시 타입이라 괜찮을 것 같긴 한데 혹시라도 왠만해서는 컨트롤러까지 트랜잭션이 오지 않을 것 같긴 한데 혹시라도 트랜잭션이 컨트롤러에 있는 경우 게다가 임베디드 타입이 아닌 엔티티를 가져오는 경우는 주의를 해야 할 수도 있다.

 

아직 문제점은 끝나지 않았다.

지금도, 

    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    join
        member m1_0 
            on m1_0.member_id=o1_0.member_id 
    fetch
        first ? rows only
2023-11-13T17:17:02.649+09:00 TRACE 1628 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [INTEGER] - [1000]
2023-11-13T17:17:02.649+09:00  INFO 1628 --- [nio-8080-exec-2] p6spy                                    : #1699863422649 | took 0ms | statement | connection 29| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first ? rows only
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first 1000 rows only;
2023-11-13T17:17:02.652+09:00 DEBUG 1628 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        m1_0.member_id,
        m1_0.city,
        m1_0.street,
        m1_0.zipcode,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.member_id=?
2023-11-13T17:17:02.652+09:00 TRACE 1628 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T17:17:02.653+09:00  INFO 1628 --- [nio-8080-exec-2] p6spy                                    : #1699863422653 | took 0ms | statement | connection 29| url jdbc:h2:tcp://localhost/./jpashop
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=?
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=1;
2023-11-13T17:17:02.654+09:00 DEBUG 1628 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        d1_0.delivery_id,
        d1_0.city,
        d1_0.street,
        d1_0.zipcode,
        d1_0.status 
    from
        delivery d1_0 
    where
        d1_0.delivery_id=?
2023-11-13T17:17:02.654+09:00 TRACE 1628 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T17:17:02.654+09:00  INFO 1628 --- [nio-8080-exec-2] p6spy                                    : #1699863422654 | took 0ms | statement | connection 29| url jdbc:h2:tcp://localhost/./jpashop
select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=?
select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=1;
2023-11-13T17:17:02.655+09:00 DEBUG 1628 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?
2023-11-13T17:17:02.655+09:00 TRACE 1628 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T17:17:02.655+09:00  INFO 1628 --- [nio-8080-exec-2] p6spy                                    : #1699863422655 | took 0ms | statement | connection 29| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=?
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=1;
2023-11-13T17:17:02.656+09:00 DEBUG 1628 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        m1_0.member_id,
        m1_0.city,
        m1_0.street,
        m1_0.zipcode,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.member_id=?
2023-11-13T17:17:02.657+09:00 TRACE 1628 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T17:17:02.657+09:00  INFO 1628 --- [nio-8080-exec-2] p6spy                                    : #1699863422657 | took 0ms | statement | connection 29| url jdbc:h2:tcp://localhost/./jpashop
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=?
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=2;
2023-11-13T17:17:02.657+09:00 DEBUG 1628 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        d1_0.delivery_id,
        d1_0.city,
        d1_0.street,
        d1_0.zipcode,
        d1_0.status 
    from
        delivery d1_0 
    where
        d1_0.delivery_id=?
2023-11-13T17:17:02.657+09:00 TRACE 1628 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T17:17:02.658+09:00  INFO 1628 --- [nio-8080-exec-2] p6spy                                    : #1699863422658 | took 0ms | statement | connection 29| url jdbc:h2:tcp://localhost/./jpashop
select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=?
select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=2;
2023-11-13T17:17:02.658+09:00 DEBUG 1628 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?

쿼리가 굉장히 많이 호출된다.

 

반복문 돌면서 Dto랑 파싱하는 과정 중 getName() 등 하면서 그 때 LAZY였던 쿼리가 날라간다.

 

 

이게 쿼리가 처음에 order 한번에 조회해 오면서 쿼리가1개 나가고,

첫번째 order 조회하면서 member, delivery 이렇게 2개,

두번째 order 조회하면서 마찬가지로 2개

총 5개가 나가야 하는데,

 

나는 7개가 나간다.

 

뭔가 하이버네이트 버그로 추측하고 있다고 한다. 버전업 되면서 바뀌었으니까.

'스프링데이터 + JPA > API 개발' 카테고리의 다른 글

9. 바로 Dto로 받기  (0) 2023.11.14
8. fetch join 최적화  (0) 2023.11.13
6. 지연로딩과 조회성능 최적화  (0) 2023.11.13
5. 조회용 샘플 데이터 입력  (0) 2023.11.12
4. API 성능 최적화  (0) 2023.11.12