Reputation: 786
I am receiving a queryParam from a controller which is a map, to query the data based on the provided map. I want to use specifications but I am not sure how can I do AND
operation between all of them. I would appreciate any suggestion.
Here is my criteria class:
public class DriverSpecs {
private final static String CAR_FIELD = "carDO";
public Specification<DriverDO> getDriversBySpecification(Map<String, String> queryParams) {
queryParams.keySet().forEach(k -> {
if (k.toLowerCase().contains("username")){
getDriversByUsername(queryParams.get(k));
} else if (k.toLowerCase().contains("rating")){
getDriversByCarRating(queryParams.get(k));
}
// ...
});
// do AND operation for all the specifications and return it
return null;
}
public static Specification<DriverDO> getDriversByUsername(String username) {
return ((root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.equal(root.get("username"), username));
}
public static Specification<DriverDO> getDriversByOnlineStatus(String onlineStatus) {
return ((root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.equal(root.get("onlineStatus"), onlineStatus));
}
public static Specification<DriverDO> getDriverByCarSeat(short seatCount) {
return specificationWithCarJoin("seatCount", seatCount);
}
public static Specification<DriverDO> getDriversByCarConvertableType(boolean convertible) {
return specificationWithCarJoin("convertible", convertible);
}
public static Specification<DriverDO> getDriversByCarRating(String rating) {
return specificationWithCarJoin("rating", rating.toUpperCase());
}
private static Specification<DriverDO> specificationWithCarJoin(String getField, Object field) {
return (root, criteriaQuery, criteriaBuilder) -> {
Join<DriverDO, CarDO> carJoin = root.join(CAR_FIELD);
return criteriaBuilder.equal(carJoin.get(getField), field);
};
}
}
Upvotes: 0
Views: 363
Reputation: 570
Use Stream API for this. Map all the parameters into a specification and then reduce it to a single specification. Like this
Optional<Specification<DriverDO>> reduce = queryParams.keySet().stream().map(k -> {
if (k.toLowerCase().contains("username")){
return getDriversByUsername(queryParams.get(k));
} else if (k.toLowerCase().contains("rating")){
return getDriversByCarRating(queryParams.get(k));
}
// ...
}).reduce((a, b) -> a.and(b));
Upvotes: 4