Как выполнить фильтрацию по входным параметрам только с использованием спецификации Jpa? - PullRequest
0 голосов
/ 02 августа 2020

Пишу интернет-магазин по покупке кофе и чая. Я использую Spring-Boot (MVC), Hibernate, JPA и PostgreSQL. В приложении у меня будет фильтр , где я буду фильтровать поиск по parameters (например, цвет чая, тип чая и т. Д. c.). Я использовал для этого Spring-Data-Jpa Specification. Я написал метод, который отлично работает и выполняет свою работу. Когда я прохожу все три parameters, он фильтрует список и выдает только те напитки, которые подходят. Но что, если пользователь не передает все параметры в фильтре. Что, если он фильтруется только по цвету чая? Что тогда делать? Возможно, вам стоит использовать if-else, но как именно?

Класс напитка:

@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;
}

Чайный класс:

public class Tea extends Drink {

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

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

СПЕЦИФИКАЦИЯ:

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);
        };
    }

Сервис:

    /**
     *
     * @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));
    }

1 Ответ

1 голос
/ 02 августа 2020

Как вы сказали, использование if сделает работу. Таким образом, вы добавите каждый предикат, если они не равны нулю, в список.

А затем просто сделайте следующее:

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);
...