英文:
How to filter on input parameters only using Jpa Specification?
问题
我正在编写一个在线咖啡和茶购买商店。我使用了Spring-Boot
(MVC
)、Hibernate
、JPA
和PostgreSQL
。在应用程序中,我将有一个筛选器,我将使用参数
来筛选搜索(例如,茶的颜色、茶的类型等)。我使用了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 = "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));
}
答案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<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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论