如何仅使用 Jpa 规范过滤输入参数?

How to filter on input parameters only using Jpa Specification?

我正在写一个在线商店来购买咖啡和茶。我使用 Spring-BootMVC)、HibernateJPAPostgreSQL。在应用程序中,我将有一个 过滤器,我将在其中按 parameters(例如,茶颜色、茶类型等)过滤搜索。为此,我使用了 Spring-Data-Jpa Specification。我写了一个工作正常的方法并完成了它的工作。当我通过所有三个 parameters 时,它会为我过滤列表并只给出适合的饮料。但是如果用户没有传递过滤器中的所有参数怎么办。如果它只根据茶的颜色过滤呢?那怎么办?也许您应该使用 if-else,但具体如何使用?

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

茶 Class:

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

如您所说,使用 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);