• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

OneToMany Many쪽의 페이지네이션 질문입니다

21.04.05 10:18 작성 조회수 451

0

안녕하세요? 섹션 4 강의 컬렉션 조회 페이징을 보고 질문 드립니다. 주문 조회 V3.1에서 페이징을 위해

jpa.properties.hibernate.default_batch_fetch_size=100, @BatchSize를 사용하거나 또는

V5에서 Map, groupBy를 이용하여 DTO 직접 조회Order에 대하여 페이징이 가능하다는 것을 알았습니다.

그런데 만약 Order 페이징 + OrderItem 페이징(예를 들어 주문을 10건 중 비싼 아이템 2건만 조회하기)같은 경우에는 어떻게 적용이 가능한가요?

public List<OrderQueryDto> findAllOpt(){
		List<OrderQueryDto> result = findOrders(); // 기존의 ToOne 쿼리

		List<Long> orderIds = result.stream()      // in 쿼리를 위한 id 뽑기
							.map(o -> o.getOrderId())
							.collect(Collectors.toList());
		
		List<OrderItemQueryDto> orderItems = findMap(orderIds);

		Map<Long, List<OrderItemQueryDto>> orderItemMap = orderItems.stream()
							.collect(Collectors.groupingBy(OrderItemQueryDto::getOrderId));	
		
		result.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));
		return result;
}

public List<OrderItemQueryDto> findMap(List<Long> orderIds) {
		return em.createQuery(
					"select new queryDto(파라미터들)" +
					" from OrderItem oi" +
					" join oi.item i" +
					" where oi.order.id in :orderIds", OrderItemQueryDto.class)
                                           .setFirstResult(0)
                                           .setMaxResults(2)
					.setParameter("orderIds", orderIds)
					.getResultList();
		)
}

이렇게 Limit를 걸었을 때 UserA 2건 뜨고 UserB는 null 이 뜨더군요. 

다른 방법을 찾아본 결과 https://bottom-to-top.tistory.com/45 처럼 방향을 반대로 하여 ManyToOne으로 조회하는 방법도 있다는것을 알았습니다.

결국엔 Order 페이징 + OrderItem 페이징 까지 접목시키려면 ManyToOne으로 조회하는 방법밖에 없을까요?

답변 2

·

답변을 작성해보세요.

1

Sunny님의 프로필

Sunny

질문자

2021.04.05

아 그런 마법의 코드 같은건 없군요 감사합니다 어떻게 해야할지 확실히 정해졌어요!

1

안녕하세요. Sunny님

이 부분은 JPA의 문제라기 보다는 관계형 데이터베이스의 한계입니다. OneToMany 관계를 조인하면 데이터가 증가해서 정확한 페이징이 불가능합니다.

반대로 ManyToOne 관계를 조인하면 데이터수가 증가하지 않기 때문에 정확한 페이징이 가능합니다.

감사합니다.