• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

주문취소 테스트시

21.08.08 00:46 작성 조회수 137

0

주문취소쪽 테스트하다가 궁금한점 있어 질문드립니다.

취소할 주문ID를 조회하고

Order order = orderRepository.findOne(orderId);

order.cancel(); 로 주문취소하기 전에 orderItems에 값이 넣어져 있는지 모르겠습니다.

Order와 OrderItem은 @OneToMany로 기본이 LAZY 로딩이라 orderItems을 직접 호출하기 전까지는 데이터를 조회하지 않는거로 알고 있는데 어떻게 orderItems에 값이 채워져서 취소가 되는지요?...

for (OrderItem orderItem : orderItems) {
orderItem.cancel();
}

저 for문 시점에 데이터를 조회하면 이해하겠는데 디버깅해보면 order를 조회할때 이미 값이 다 채워져 있습니다...

답변 2

·

답변을 작성해보세요.

2

OMG님의 프로필

OMG

2021.08.08

안녕하세요. 궁그미님, 공식 서포터즈 OMG입니다.

JPA를 학습하시면서 프록시에 대해서 학습을 하신적이 있으신가요?

관련하여 JPA 기본편 학습을 권장드립니다.

추가적으로 부연설명 하나만 드리면 아래는 서로 다른 두 개의 포스팅을 참고하였습니다.

공통으로 보이는 특이한 키워드가 보일까요?

그 키워드를 올리신 디버깅 화면에서 찾아보시겠어요?

제가 드린 힌트를 바탕으로 궁금하신 사항과 연관지어 학습을 이어나가시면 될 것 같습니다.

 

참고

(JPA - 4) 프록시 객체, 즉시로딩, 지연로딩 | KihoonKim:Dev

[jpa] 프록시와 연관관계 관리 | 기록은 기억의 연장선 (joont92.github.io)

감사합니다. 

궁그미님의 프로필

궁그미

질문자

2021.08.11

이해가 잘안되어 재질문 드립니다...

Order order = orderRepository.findOne(orderId);  실행시 order.orderItems는 프록시인거는 이해했는데요.

프록시는 실제 데이터 조회할때 초기화해서 데이터 가져오는데

order.cancel() 내부 비즈니스 로직

for(OrderItem orderItem : orderItems) {

   orderItem.cancel();

}

실행하기 전에 Order order = orderRepository.findOne(orderId);  조회할때 이미 orderItems에 값(id, price, stockquentity)이 채워져 있어  헷갈리네요. 원래 그런건가해서요.

프록시 상태일때 엔티티를 참조만하는게 아니라 값도 가지고 있고, 실제 데이터 조회할 때 다시 가지고 오는건지요?

학습해서 이해한 내용은 엔티티를 참조만하고 실제 데이터는 조회할때 초기화해서 가지고 오는거로 알고 있습니다...

관련해서 별도로 테스트해본 부분도 잘 이해가 안되어 질문 드려요.

아래 첫번째 캡쳐는 member insert하고 영속성 컨텍스트 초기화하고 프록시로 조회하여 select 쿼리가 안나가는거는 맞는데

두번째 캡쳐에서 어딘가에 디버깅 모드를 걸어서 테스트하면 프록시로 조회할때 select 쿼리가 나갑니다. 이것도 왜 그런지 모르겠네요...

두 테스트 차이는 단지 브레이크 포인트입니다.

1

안녕하세요. 궁그미님

처음 테스트 코드를 보셔야 합니다.

orderService.order()를 호출하면 Order와 OrderItem이 모두 만들어진 상태로 유지됩니다.

따라서 다시 조회해도 이미 Order-> OrderItem이 함께 존재하게 됩니다.

처음 테스트 코드에서 em.flush(); 이후에 em.clear()로 영속성 컨텍스트를 완전히 지우고

주문을 em.find()로 처음부터 다시 조회하셔야 프록시 상태의 orderItems를 볼 수 있습니다.

추가로 디버그 모드에서 Lazy 엔티티를 확인하게 되면 초기화 처리가 되어버립니다.

감사합니다.