❄️ 내일배움캠프 7기

[Trouble Shooting] 플러스주차 개인과제

Genie_. 2024. 12. 18. 19:42
728x90
반응형

동적 쿼리에 대한 이해

// 기존엔 이런 식으로 파라미터에 따라 다른 메서드를 호출하고 if-else를 남발했었다.
public List<Reservation> searchReservations(Long userId, Long itemId) {
    if (userId != null && itemId != null) {
        return reservationRepository.findByUserIdAndItemId(userId, itemId);
    } else if (userId != null) {
        return reservationRepository.findByUserId(userId);
    } else if (itemId != null) {
        return reservationRepository.findByItemId(itemId);
    } else {
        return reservationRepository.findAll();
    }
}
  • 설명
    • userId, itemId 조건 데이터 존재 여부에 따라 동적으로 검색을 수행합니다.
  • 현재 조건
    • 데이터 존재 여부에 따라 다른 JPA가 각각 호출되고 있습니다.

QueryDSL로 동적 쿼리 적용

하나의 메서드 안에서 userId와 itemId가 있든, 없든, 필요한 조건만 적용할 수 있게!

public List<ReservationResponseDto> searchAndConvertReservations(Long userId, Long itemId) {
        List<Reservation> reservations = searchReservations(userId, itemId);
        return convertToDto(reservations);
    }

    public List<Reservation> searchReservations(Long userId, Long itemId) {
        // QueryDSL 사용하기 위ㅎ서 Q타입 객체 선언(Reservation,user,item 엔티티 기반)
        QReservation reservation = QReservation.reservation;
        QUser user = QUser.user;
        QItem item = QItem.item;

        // selectFrom(조회대상)을 reservation 엔티티로 지정
        // 연관관계가 있는 User, Item 엔티티를 LEFT JOIN 해주면서, FetchJoin으로 한 번에 연관 데이터 가져옴
        JPAQuery<Reservation> query = queryFactory
                .selectFrom(reservation)
                .leftJoin(reservation.user, user).fetchJoin()
                .leftJoin(reservation.item, item).fetchJoin();

        // userId와 itemId가 null이 아닐 경우에만 where 조건 추가
        // -> userId, itemId 중 null인게 있을때, where 조건 적용하지 않고, 모든 예약을 조회하거나 하나의 조건만 설정가능
        if (userId != null) {
            query.where(reservation.user.id.eq(userId));
        }

        if (itemId != null) {
            query.where(reservation.item.id.eq(itemId));
        }

        // 쿼리 실행하고 결과 리스트 반환!
        return query.fetch();
    }

Fetch Join으로 N+1 문제 해결

위의 코드에서 .fetchJoin()을 사용했다. 이건 조회할 때 User와 Item도 같이 한 번에 가져온다.
이렇게 하면 나중에 reservation.getUser()나 reservation.getItem()을 호출하더라도 추가 쿼리를 날릴 필요가 없어져 N+1 문제가 사라진다.

728x90
반응형