简体   繁体   中英

How to filter on input parameters only using Jpa Specification?

I am writing an online-store to buy coffee and tea. I use Spring-Boot ( MVC ), Hibernate , JPA and PostgreSQL . In the application, I will have a filter , where I will filter the search by parameters (for example, tea color, tea type, etc.). I used the Spring-Data-Jpa Specification for this. I wrote a method that works fine and does its job. When I pass all three parameters , it filters the list for me and gives out only those drinks that fit. But what if the user does not pass all the parameters in the filter. What if it filters only by the color of the tea? What to do then? Perhaps you should use if-else , but how exactly?

Drink Class:

@Inheritance(strategy = InheritanceType.JOINED)
public class Drink {

    // Fields
    //
    private @Id
    @GeneratedValue
    Long id;

    private String name;

    private BigDecimal price;

    private String about;

    @Column(name = "is_deleted")
    private boolean isDeleted;

    // Relationships
    //
    @ManyToOne
    @JoinColumn(name = "packaging_id")
    private Packaging packaging;

    @ManyToOne
    @JoinColumn(name = "manufacturer_id")
    private Manufacturer manufacturer;

    @ManyToOne
    @JoinColumn(name = "country_id")
    private Countries countries;
}

Tea Class:

public class Tea extends Drink {

    // Relationships
    //
    @ManyToOne
    @JoinColumn(name = "type_id")
    private TeaType teaType;

    @ManyToOne
    @JoinColumn(name = "color_id")
    private TeaColor teaColor;
}

SPECIFICATION:

public class TeaSpecification {

    public static Specification<Tea> getTeasByFilter(Long colorId, Long typeId, Long countryId) {
        return (root, query, criteriaBuilder) -> {
            Predicate colorPredicate = criteriaBuilder
                    .equal(root.get(Tea_.teaColor).get(TeaColor_.id), colorId);
            Predicate typePredicate = criteriaBuilder
                    .equal(root.get(Tea_.teaType).get(TeaType_.id), typeId);
            Predicate countryPredicate = criteriaBuilder
                    .equal(root.get(Tea_.countries).get(Countries_.id), countryId);
            return criteriaBuilder.and(colorPredicate, typePredicate, countryPredicate);
        };
    }

Service:

    /**
     *
     * @param page
     * @param pageSize
     * @param colorId
     * @param typeId
     * @param countryId
     * @return filtered Coffees(DTOs)
     */
    public PageDTO<DrinkDTO> findAllByFilter(int page, int pageSize, Long colorId,
                                             Long typeId, Long countryId) {

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

        final Page<Tea> teas = teaRepository
                .findAll(TeaSpecification.getTeasByFilter(colorId, typeId, countryId), pageRequest);

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

As you said using if will do the job. So you will add each predicate if they are not null to a list.

And then just do the following:

List<Predicate> predicates = new ArrayList<>();

// here your conditionals to create/add the predicates


Predicate query = criteriaBuilder.and(predicates.toArray(new Predicate[0]));
return criteriaBuilder.and(query);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM