I have a need to use JpaSpecificationExecutor. Initially, I assumed that one parameter would be given as input and I would process it like this:
List<Car> findCarsByParameters(
String brand,
Integer color
) {
Specification<Car> querySpec = new Specification<Car>() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if (!brand.isEmpty()) {
predicates.add(criteriaBuilder.like(root.get("brand"), brand));
}
if (color != null) {
predicates.add(criteriaBuilder.equal(root.get("color"), color));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
return carRepository.findAll(querySpec);
}
CarRepository :
public interface CarRepository extends CrudRepository<Car, Long>, JpaSpecificationExecutor
However, I need to be able to work with:
List<String> brands,
List<Integer> colors
And in response to me came all the options for suitable machines.
For example input:
brand = {honda, toyota},
color = {0x00ffff, 0x800000}
At the output, I want to get all the machines whose properties fall under one of the following conditions:
{honda,0x00ffff};{honda,0x800000};{toyota,0x00ffff};{toyota,0x800000}
How do I need to modify my code so that it works like I gave in the example? Or where can I read about it?
CodePudding user response:
This article perfectly explains what you need.
You basically iterate through the List<Brand>
, create a list of brand predicates then consider this list as one block of predicate.
List<Car> findCarsByParameters(
List<String> brands,
List<Integer> colors
) {
Specification<Car> querySpec = new Specification<Car>() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
List<Predicate> brandPredicates = new ArrayList<>();
if (brands != null && !brand.isEmpty()) {
brandPredicates = brands.stream()
.map((brand) -> criteriaBuilder.like(root.get("brand"), brand))
.collect(Collectors.toList());
}
Predicate predicateForBrand = criteriaBuilder.or(brandPredicates.toArray(Predicate[]::new));
List<Predicate> colorPredicates = new ArrayList<>();
if (colors != null && !colors.isEmpty()) {
colorPredicates = colors.stream()
.map((color) -> criteriaBuilder.like(root.get("color"), color))
.collect(Collectors.toList());
}
Predicated predicateForColor = criteriaBuilder.or(colorPredicates.toArray(Predicate[]::new));
return criteriaBuilder.and(predicateForColor, predicateForBrand);
}
};
return carRepository.findAll(querySpec);
}