Project/Team Project(딱좋은여행)

항공 상품 필터 및 페이징 처리

해달's code 2025. 3. 22. 02:12
public class AirSpecification {

    public static Specification<Air> filterBy(
            List<String> airlines, List<String> departs, List<String> arrives, String departTimeStart, String departTimeEnd, Integer minPrice, Integer maxPrice
    ) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 항공사 필터 (체크박스 선택)
            if (airlines != null && !airlines.isEmpty()) {
                predicates.add(root.get("airline").in(airlines));
            }
            // 출발지 필터 (체크박스 선택)
            if (departs != null && !departs.isEmpty()) {
                predicates.add(root.get("depart").in(departs));
            }

            // 도착지 필터 (체크박스 선택)
            if (arrives != null && !arrives.isEmpty()) {
                predicates.add(root.get("arrive").in(arrives));
            }

            // 출발 시간 필터
            if (departTimeStart != null && departTimeEnd != null) {
                predicates.add(criteriaBuilder.between(root.get("depart_time"), departTimeStart, departTimeEnd));
            }

            // 가격 범위 필터
            if (minPrice != null && maxPrice != null) {
                predicates.add(criteriaBuilder.between(root.get("price"), minPrice, maxPrice));
            }

            return predicates.isEmpty() ? criteriaBuilder.conjunction() : criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
}

처음 필터 적용 방법 Specification 적용

복잡한 쿼리를 처리하기 위함

사용하기 위해 하단 레포지토리에 추가해줘야함

public interface AirRepository extends JpaRepository<Air, Long>, JpaSpecificationExecutor<Air> {

    // 페이징과 정렬을 지원하는 Specification 기반 쿼리
    Page<Air> findAll(Specification<Air> spec, Pageable pageable);

}

만든 쿼리 사용방법

@RestController
@RequiredArgsConstructor
@RequestMapping("/air")
public class AirController {

    private final AirService airService;

    // 전체 항공 상품 (페이징)
    @GetMapping
    public Page<Air> getAllAir(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "price,asc") String sortBy
    ) {
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Order.by(sortBy.split(",")[0]).with(Sort.Direction.fromString(sortBy.split(",")[1]))));
        return airService.getAllAirList(pageable);
    }

    // 필터링된 항공 상품 (페이징)
    @GetMapping("/search")
    public Page<Air> searchAir(
            @RequestParam(required = false) List<String> airlines,
            @RequestParam(required = false) List<String> departs,
            @RequestParam(required = false) List<String> arrives,
            @RequestParam(required = false) String departTimeStart,
            @RequestParam(required = false) String departTimeEnd,
            @RequestParam(required = false) Integer minPrice,
            @RequestParam(required = false) Integer maxPrice,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "price,asc") String sortBy
    ) {
        Specification<Air> spec = AirSpecification.filterBy(airlines, departs, arrives, departTimeStart, departTimeEnd, minPrice, maxPrice);
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Order.by(sortBy.split(",")[0]).with(Sort.Direction.fromString(sortBy.split(",")[1]))));
        return airService.getFilteredAirList(spec, pageable);
    }
}
@Service
@RequiredArgsConstructor
public class AirService {

    private final AirRepository airRepository;

    // 필터 적용 + 페이징 처리된 항공 상품 조회
    public Page<Air> getFilteredAirList(Specification<Air> spec, Pageable pageable) {
        return airRepository.findAll(spec, pageable);
    }

    // 필터 없이 전체 항공 상품 조회 (처음 페이지 진입 시)
    public Page<Air> getAllAirList(Pageable pageable) {
        return airRepository.findAll(pageable);
    }
}

다음에 querydsl로 조건을 더 걸어서 변경작업중