작성
·
94
0
public List<Order> findSearchOrders(OrderSearch orderSearch){ return em.createQuery("select o from Order o join o.member m" + " where o.orderStatus = :status" + " and m.name like :name", Order.class) .setParameter("status", orderSearch.getOrderStatus() ) .setParameter("name", orderSearch.getMemberName()) .setMaxResults(1000) .getResultList(); }
public List<OrderQueryDto> findQueryOrder() {
List<OrderQueryDto> result = findAllOrder();
for (OrderQueryDto order : result) {
List<OrderItemQueryDto> orderItems = findOrderItem(order.getId());
order.setOrderItems(orderItems);
}
return result;
}
public List<OrderItemQueryDto> findOrderItem(Long orderId) {
String query = "select new jpabook.jpashop.repository.order.query." +
" OrderItemQueryDto(oi.order.id, oi.orderPrice, oi.count )" +
" from OrderItem oi " +
" join oi.item i" +
" where oi.order.id = :orderId";
return em.createQuery(query,OrderItemQueryDto.class)
.setParameter("orderId", orderId)
.getResultList();
}
public List<OrderQueryDto> findAllOrder(){
String query = "select new jpabook.jpashop.repository.order.query." +
" OrderQueryDto(o.id, m.name, d.address, o.orderStatus, o.orderDate) " +
" from Order o " +
" join o.member m" +
" join o.delivery d";
return em.createQuery(query, OrderQueryDto.class).getResultList();
}
첫번째 코드 블럭은 order를 select 할때 member를 join 하면 member를 프록시 객체로 가져오는걸로 알고 있습니다.
join fetch 를 하게 되면 바로 객체로 가지고 오는걸로 알고 있습니다.
하지만, 두번째 코드 블럭은 그냥 join을 했는데, 왜 프록시 객체에서 객체로 전환? 프록시 객체가 객체를 가르키는 행위를 하지않고도 dto에 바로 삽입이 가능한가요?
ex) order.getName() , member.getName()
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
질문자님께서는 join
과 fetch join
의 차이점을 궁금해하시며, 특히 DTO 조회시에 간접적으로 엔티티 프록시가 아닌 직접 객체를 처리하는 방법에 대해 질문하셨습니다. 관련하여, fetch join
과 일반 join
의 동작 방식 차이와 DTO 조회시의 엔티티 처리 방법을 설명드리겠습니다.
join
은 연관된 엔티티를 함께 조회하기 위해 SQL의 JOIN을 사용합니다. Hibernate나 JPA에서는 이때 해당 연관 필드를 프록시 객체로 초기화하여 사용자가 실제로 해당 데이터에 접근할 때(Lazy Loading) 데이터베이스에서 해당 객체를 조회합니다.fetch join
은 연관된 엔티티를 즉시 로딩(Eager Loading)으로 함께 조회합니다. 즉, fetch join
을 사용하면, 조회 쿼리를 실행할 때 연관된 엔티티도 함께 조회되어 프록시 객체가 아닌 실제 엔티티 데이터를 가지게 됩니다. 이는 성능 최적화에 유리할 수 있지만, 너무 많은 데이터를 불필요하게 조회할 위험도 있습니다.질문하신 바에 따르면, DTO 조회시에 join
만 사용했음에도 불구하고 실제 엔티티 객체가 아닌 프록시 객체 없이 데이터를 처리할 수 있는 이유에 대해 궁금해 하셨습니다. 이는 JPQL이나 QueryDSL 등을 통한 직접적인 DTO 조회 과정에서, 조회 대상이 되는 엔티티의 필드를 명시적으로 선택하여 조회하기 때문입니다. DTO로 직접 조회하는 경우, “select new” 절을 사용하여 필요한 필드를 직접 명시하므로, 해당 필드들은 이미 초기화된 상태로 조회됩니다. 따라서 프록시 객체로의 추가적인 접근이나 초기화 과정 없이, 질의 결과로 바로 반환되는 값들을 DTO에 담아낼 수 있습니다.
"select new jpabook.jpashop.repository.order.query.OrderQueryDto(...)"
위와 같은 방식으로 직접 DTO 객체를 생성하는 쿼리에서는 필요한 데이터만 추출하여 사용하기 때문에 fetch join
을 사용하지 않고도, Lazy Loading 없이 필요한 정보를 바로 조회할 수 있습니다.
관련하여 참고할 만한 내용으로, “9분30초 findOrderDtos()관련 질문입니다.“와 “dto join 과 일반 fetch join 차이점에 대해 질문 있습니다.”에서는 DTO 조회에 대한 깊이 있는 논의가 이루어졌습니다. 일반 join
과 fetch join
의 사용례에 대해 더 깊이 있는 이해를 돕는 자료가 될 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.