如何仅使用 Jpa 规范过滤输入参数?
How to filter on input parameters only using Jpa Specification?
我正在写一个在线商店来购买咖啡和茶。我使用 Spring-Boot
(MVC
)、Hibernate
、JPA
和 PostgreSQL
。在应用程序中,我将有一个 过滤器,我将在其中按 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);
我正在写一个在线商店来购买咖啡和茶。我使用 Spring-Boot
(MVC
)、Hibernate
、JPA
和 PostgreSQL
。在应用程序中,我将有一个 过滤器,我将在其中按 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);