Skip to content
Advertisement

Working with multiple parameters in CriteriaBuilder

I have a need to use JpaSpecificationExecutor. Initially, I assumed that one parameter would be given as input and I would process it like this:

List<Car> findCarsByParameters(
            String brand,
            Integer color
    ) {
        Specification<Car> querySpec = new Specification<Car>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (!brand.isEmpty()) {
                    predicates.add(criteriaBuilder.like(root.get("brand"), brand));
                }
                if (color != null) {
                    predicates.add(criteriaBuilder.equal(root.get("color"), color));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return carRepository.findAll(querySpec);
    }

CarRepository :

public interface CarRepository extends CrudRepository<Car, Long>, JpaSpecificationExecutor 

However, I need to be able to work with:

List<String> brands,
List<Integer> colors

And in response to me came all the options for suitable machines.

For example input:

brand = {honda, toyota},
color = {0x00ffff, 0x800000}

At the output, I want to get all the machines whose properties fall under one of the following conditions:

{honda,0x00ffff};{honda,0x800000};{toyota,0x00ffff};{toyota,0x800000}

How do I need to modify my code so that it works like I gave in the example? Or where can I read about it?

Advertisement

Answer

This article perfectly explains what you need.

You basically iterate through the List<Brand>, create a list of brand predicates then consider this list as one block of predicate.

List<Car> findCarsByParameters(
        List<String> brands,
        List<Integer> colors
) {
    Specification<Car> querySpec = new Specification<Car>() {
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
            List<Predicate> brandPredicates = new ArrayList<>();

            if (brands != null && !brand.isEmpty()) {
                brandPredicates = brands.stream()
                                        .map((brand) -> criteriaBuilder.like(root.get("brand"), brand))
                                        .collect(Collectors.toList());
            }

            Predicate predicateForBrand = criteriaBuilder.or(brandPredicates.toArray(Predicate[]::new));
            List<Predicate> colorPredicates = new ArrayList<>();

            if (colors != null && !colors.isEmpty()) {
                colorPredicates = colors.stream()
                                        .map((color) -> criteriaBuilder.like(root.get("color"), color))
                                        .collect(Collectors.toList());
            }

            Predicated predicateForColor = criteriaBuilder.or(colorPredicates.toArray(Predicate[]::new));
            return criteriaBuilder.and(predicateForColor, predicateForBrand);
        }
    };
    return carRepository.findAll(querySpec);
}
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement