Artur Vartanyan
Artur Vartanyan

Reputation: 829

How to filter an object using multiple parameters in the specification method?

I am writing an online-store using Spring-Boot (MVC) and Hiberbate. I decided to use the Jpa specification to filter the list of objects. For example, filter coffee with parameters of roast and type of coffee. I did all the guide and everything worked for me, but with only one input parameter, roasting. How to add one or more parameters for the filter, please tell me...

For example my realisation:

public class CoffeeSpecification {

    public static Specification<Coffee> getCoffeesByRoasting(String name) {
        return (root, query, criteriaBuilder) -> {
            Join<Object, Object> roastingJoin = root.join(Coffee_.ROASTING);
            return criteriaBuilder.equal(roastingJoin.get(Roasting_.NAME), name);
        };
    }}

Service:

public PageDTO<DrinkDTO> findAllFilter(int page, int pageSize, String roastingName, String coffeeType) {

        PageRequest pageRequest = PageRequest.of(page, pageSize, Sort.by("price").ascending());

        final Page<Coffee> coffees = coffeeRepository
                .findAll(CoffeeSpecification.getCoffeesByRoasting(roastingName), pageRequest);

        return new PageDTO<>(drinkMapper.drinksToDrinksDTO(coffees));
    }

Controller:

@GetMapping("/coffees")
    public PageDTO<DrinkDTO> getAllCoffees(@RequestParam(value = "page", defaultValue = "1") int page,
                                           @RequestParam(value = "page_size", defaultValue = "5") int pageSize,
                                           @RequestParam String roastingName) {

        return coffeeService.findAllFilter(page, pageSize, roastingName, coffeeType);
    }

Upvotes: 1

Views: 2302

Answers (1)

Vipul Kumar
Vipul Kumar

Reputation: 479

I have used JpaSpecification for filtering area based on mobile and pincode and using the following code to achieve the same

public class UserAreaMappingSpecifications {
    public static Specification<UserAreaMapping> userAreaMappingByFilter(String pinCode, String mobile) {
        return (Specification<UserAreaMapping>) (root, query, cb) -> {
            Predicate pinCodePredicate = Objects.nonNull(pinCode) ? cb.equal(root.get("pinCode"), pinCode) : cb.conjunction();
            Predicate mobilePredicate = Objects.nonNull(mobile) ? cb.equal(root.get("mobile"), mobile) : cb.conjunction();
            return cb.and(pinCodePredicate, mobilePredicate);
        };
    }
}

I have used predicates and combining them using and operator.

Possibly, you can also do with your implementation as well

public class CoffeeSpecification {

    public static Specification<Coffee> getCoffeesByRoasting(String name, String type) {
        return (root, query, criteriaBuilder) -> {
            Join<Object, Object> roastingJoin = root.join(Coffee_.ROASTING);
            Join<Object, Object> typeJoin = root.join(Coffee_.TYPE);
            Predicate rostingPredicate = criteriaBuilder.equal(roastingJoin.get(Roasting_.NAME), name);
            Predicate typePredicate = criteriaBuilder.equal(roastingJoin.get(Roasting_.TYPE), type);
            return cb.and(rostingPredicate, typePredicate);

        };
    }}

Hope I was able to solve your problem.

Note: You can use or() operator based on your requirement instead of using and() operator.

Upvotes: 1

Related Questions