使用Jpa规范仅过滤输入参数的方法是什么?

huangapple go评论48阅读模式
英文:

How to filter on input parameters only using Jpa Specification?

问题

我正在编写一个在线咖啡和茶购买商店。我使用了Spring-BootMVC)、HibernateJPAPostgreSQL。在应用程序中,我将有一个筛选器,我将使用参数来筛选搜索(例如,茶的颜色、茶的类型等)。我使用了Spring-Data-Jpa Specification来实现这一点。我编写了一个可以正常工作并完成其工作的方法。当我传递所有三个参数时,它会为我筛选列表,并只输出符合条件的饮料。但如果用户在筛选器中没有传递所有参数怎么办?如果只按茶的颜色进行筛选怎么办?那么应该怎么做呢?也许你应该使用if-else,但具体应该怎么做呢?

饮料类:

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

    // 字段
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private BigDecimal price;

    private String about;

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

    // 关联关系
    @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 {

    // 关联关系
    @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));
}
英文:

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 = &quot;is_deleted&quot;)
    private boolean isDeleted;

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

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

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

Tea Class:

public class Tea extends Drink {

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

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

SPECIFICATION:

public class TeaSpecification {

    public static Specification&lt;Tea&gt; getTeasByFilter(Long colorId, Long typeId, Long countryId) {
        return (root, query, criteriaBuilder) -&gt; {
            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&lt;DrinkDTO&gt; findAllByFilter(int page, int pageSize, Long colorId,
                                             Long typeId, Long countryId) {

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

        final Page&lt;Tea&gt; teas = teaRepository
                .findAll(TeaSpecification.getTeasByFilter(colorId, typeId, countryId), pageRequest);

        return new PageDTO&lt;&gt;(drinkMapper.drinksToDrinksDTO(teas));
    }

答案1

得分: 1

根据你说的,使用条件语句(if)就可以完成任务。所以,如果它们不为空,你将把每个谓词添加到一个列表中。

然后只需执行以下操作:

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

// 这里是创建/添加谓词的条件语句


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

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&lt;Predicate&gt; predicates = new ArrayList&lt;&gt;();

// here your conditionals to create/add the predicates


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

huangapple
  • 本文由 发表于 2020年8月2日 19:32:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63215482.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定