-
카테고리
-
세부 분야
백엔드
-
해결 여부
해결됨
ordersV2(url : api/v2/orders) 실행 시 쿼리 질문
22.09.09 23:11 작성 조회수 297
1
실행창을 확인해보니 해당 API 호출 시 쿼리가
order -> member -> delivery -> orderitems -> item -> (2) -> item -> ( 1 ) ->member -> delivery -> orderitems ->item -> (2)->item
순으로 나갑니다.
(1)에 두 번째 order 을 조회하는 쿼리가 나가야 하지않나요?
처음 findAllByString 메서드로 두 개의 Order 모두 로딩했다.
처음 로딩한 Order 을 1차캐시에서 가져왔다.
둘 중 뭐가 맞는지 궁금합니다.
다음으로
(2) 에는 orderitem 이 조회 된다고 생각했었는데 왜 한번만 조회 된 후 item이 두 번 조회되는건지 궁금합니다.
다음으로
orderItem 이 로딩되는 시점은 orderItem.getItem()
이고
Item의 로딩 시점은 orderItem.getItem().getName(); 이라고 알고 있는데 맞는지 궁금합니다.
= 로딩이 '해당객체'의 조회 시점인지 '해당객체의 필드에 접근' 하는 시점인지 궁금합니다.
답변을 작성해보세요.
0
y2gcoder
2022.09.10
안녕하세요. tksrleo123님, 공식 서포터즈 y2gcoder입니다.
우선 말씀해주신 것을 보니 강의 자료 상
이 부분을 말씀하신다고 이해하고 설명드리겠습니다.
(1) order들은 이미 findAll() 때 query를 통해 order를 다 가져온 상황입니다. 그래서 다시 order를 부를 필요가 없습니다.
(2) 이 때는 dto에서 프록시가 초기화되는 순서를 보셔야 합니다.
위의 OrderDto의 생성자 부분에서 orderItems 부분을 봐주시겠습니까?
그리고 말씀하신 것처럼 orderItems 의 프록시를 초기화할 때 발생하는 SQL 문을 봐주시면
where 조건에서 해당 orderItem 하나만 들고오는 것이 아니라 order_id를 이용해 해당 orderItems를 전부 가져왔습니다.
따라서 (2)에서 다시 orderItem을 불러오지 않습니다. 왜냐하면 이미 orderItem들을 다 갖고 있기 때문입니다.
감사합니다.
tksrleo123
질문자2022.09.10
답변감사합니다!!!
그렇다면 혹시 orderitem 두개를 가져오는 순간은 order.getOrderItems() 이때 인가요? 아니면 .stream() 을 열 때 가져오나요?
저는 프록시객체를 초기화 시키는 타이밍이 해당 객체에 접근 할 때 라고 알고 있어서 orderitem의 필드에 접근 할 때로 이해했습니다.
처음에는 OrderItemDto에서 orderItem.getItem() 순간에 orderitem이 초기화 되는 줄 알았지만 orderItem이 두 개가 동시에 초기화 되는 것으로 보아 이 부분은 제외했습니다.(stream이라 1개씩 초기화 되는 것으로 생각했습니다!)
y2gcoder
2022.09.10
저도 사실 궁금해서 디버깅이랑 로깅을 통해서 실험을 해봤더니, 말씀하신대로 order.getOrderItems().stream().map().collect(toList()); 부분에서 SQL이 나가는 것을 확인했습니다. 아마 stream 의 동작방식과 관련이 있는 것 같은데 먼저 리스트를 형성하고 map을 이용해서 dto를 만들어서 넣기 전에 orderItem 첫 원소를 불러오는 과정에서 sql이 날아가는 것 같습니다.
혹시나 눈으로 보길 원하신다면 강의 소스를 디버깅으로 켜시고 브레이크포인트를 걸어서 확인해보시면 재밌을 것 같습니다!
tksrleo123
질문자2022.09.10
아하 디버깅까지 해주시다니.. 정말 감사합니다! stream은 최종 연산까지 동작을 지연시키는 걸 잊고있어서 헷갈렸네요! 저도 디버깅 직접 해보겠습니다 꿀팁 감사합니다!
답변 1