Я реализовал фильтр, используя jpql Query для данных JPA.
Я использую этот класс в качестве фильтра;
@NoArgsConstructor
@Getter
@Setter
@ToString
public class FilterTO {
private Double priceMin;
private Double priceMax;
private List<Long> categories;
private List<String> brands;
public FilterTO(Double priceMin, Double priceMax, List<Long> categories, List<String> brands) {
this.priceMin = (priceMin == null)? 0 : priceMin;
this.priceMax = (priceMax == null)? Double.MAX_VALUE: priceMax;
this.brands = (brands == null || brands.isEmpty())? null : brands;
this.categories = (categories == null || categories.isEmpty())? null : categories;
}
}
И это метод и запрос, который я использую;
@Query("SELECT p FROM Product p WHERE " +
"p.price * (1 - p.discount) BETWEEN :#{#filter.getPriceMin()} AND :#{#filter.getPriceMax()} " +
"AND ( p.brand IN :#{#filter.getBrands()} OR :#{#filter.getBrands()} IS NULL) " +
"AND ( p.category.id IN (SELECT DISTINCT c.id FROM Category c " +
"WHERE c.parent.id IN :#{#filter.getCategories()}) OR p.category.id IN :#{#filter.getCategories()} OR :#{#filter.getCategories()} IS NULL) ")
Page<Product> findByFilter(@Param("filter") FilterTO filter, Pageable pageable);
Это запрос в чистой версии:
SELECT p FROM Product p WHERE p.price * (1 - p.discount) BETWEEN :#{#filter.getPriceMin()} AND :#{#filter.getPriceMax()}
AND ( p.brand IN :#{#filter.getBrands()} OR :#{#filter.getBrands()} IS NULL)
AND ( p.category.id IN (SELECT DISTINCT c.id FROM Category c WHERE c.parent.id IN :#{#filter.getCategories()}) OR p.category.id IN :#{#filter.getCategories()} OR :#{#filter.getCategories()} IS NULL)
Так что в основном я фильтрую по цене, категориям и брендам. Если список категорий пуст, я игнорирую его, а если список брендов пуст, я тоже игнорирую.
Этот же запрос прекрасно работает во H2, но когда мы попытались перейти на рабочий процесс на MySQL, он выдает эту ошибку: java.sql.SQLException: операнд должен содержать 1 столбец (ы)