해결된 질문
작성
·
188
0
@GetMapping("/api/v1/orders")
public List<Order> ordersV1() {
List<Order> all = orderRepository.findAll();
for (Order order : all) {
order.getMember().getName(); //Lazy 강제 초기화
order.getDelivery().getAddress(); //Lazy 강제 초기화
List<OrderItem> orderItems = order.getOrderItems();
orderItems.stream().forEach(o -> o.getItem().getName()); //Lazy 강제 초기화
}
return all;
}
첫 질문
Lazy방식이기에 조인되어 있는 필드를 가져오지 못하기에
member와 delivery는 One이기 때문에 get으로 초기화 하고
orderItem은 Many이기 때문에 List형식으로 stream으로 초기화 하는걸로 이해해도 될까요?
강제 초기화를 하는 이유는 값을 넣어주기 위해..? 인가요..?
두번째 질문
orderItems.stream().forEach(o -> o.getItem().getName());
이 부분 코드 제가 이해한게 맞는지 확인부탁드립니다.
o(orderItems 컬렉션에서 하나하나)에서 getItem().getName()를 가져와서 반환할 것이다.
근데 getName(이름 가져오기)만 하는데 Item의 모든 api값을 가져오는것 같아서 질문드립니다.
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
질문자님께서 질문하신, 스프링 부트와 JPA 활용 과정에서 Lazy 강제 초기화와 관련된 내용에 대해 답변해 드리겠습니다.
첫 번째 질문에 대해서는, 맞습니다. JPA에서 Lazy 로딩은 연관된 엔티티를 실제 사용하는 시점까지 로딩을 지연시키는 방식입니다. 여기서 order.getMember().getName()
과 order.getDelivery().getAddress()
를 호출함으로써 각각 멤버와 배송 정보를 실제로 사용하는 시점이 되어 해당 정보를 로딩하게 되며, 이것을 강제 초기화라고 합니다. orderItems.stream().forEach(o -> o.getItem().getName());
에서는 OrderItem의 컬렉션에 대해 스트림을 사용하여 각 아이템의 이름을 가져오는 과정에서 아이템 엔티티 역시 강제로 초기화하게 됩니다. 이러한 초기화는 API 응답 시에 해당 정보들이 필요하기 때문에 실행됩니다.
두 번째 질문에 대한 부분은, orderItems.stream().forEach(o -> o.getItem().getName());
이 코드는 각 OrderItem에 대해 관련 Item 엔티티를 로딩하게 하여 getName()
을 호출합니다. 이 과정에서 각 Item의 getName()
메소드 호출이 목적이지만, 실제로 JPA 구현체(Hibernate 등)는 연관된 엔티티의 프록시를 초기화하는 과정에서 해당 엔티티의 모든 속성을 로딩하게 됩니다. 따라서 getName()
을 호출하더라도 내부적으로는 해당 Item 엔티티의 모든 속성 값을 데이터베이스로부터 로딩합니다. 이는 JPA의 로딩 전략과 프록시 초기화의 특성 때문에 발생합니다.
이러한 내용에 대해 질문자님의 이해를 돕기 위해 유사한 질문에서의 답변 및 설명을 찾아볼 수 있습니다. 예를 들어, OrderItems까지 같이 조회되는 이유가 궁금합니다!에서 유사한 컨텍스트로 Lazy 로딩과 강제 초기화에 대한 해명이 이루어졌습니다. 또한 orderItem LAZY 로딩 질문에서도 Lazy 로딩 시 일어날 수 있는 현상과 관련된 설명이 이루어진 바 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.