如果给定@RequestParameter,则按其值过滤,如果没有,则不执行任何操作[重复]
Posted
技术标签:
【中文标题】如果给定@RequestParameter,则按其值过滤,如果没有,则不执行任何操作[重复]【英文标题】:If @RequestParameter is given, filter by it's value, if not do nothing [duplicate] 【发布时间】:2021-12-20 03:32:40 【问题描述】:我正在尝试使用@RequestParam,如果给定了值,它应该通过这个参数从数据库中找到的所有项目中过滤,如果没有,它应该什么都不做。我还想问一下函数式编程在这里是否很好用。
这是我的汽车课:
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import javax.persistence.*;
@Data
@Entity
@Table(name = "Cars")
public class Car
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Setter(AccessLevel.NONE)
private Long Id;
private int yearOfProduction;
private int price;
private String color;
private String brand;
private String model;
@ManyToOne
@JoinColumn(name = "customer")
private Customer customer;
public Car()
public Car(int yearOfProduction, int price, String color, String brand, String model)
this.yearOfProduction = yearOfProduction;
this.price = price;
this.color = color;
this.brand = brand;
this.model = model;
这是我设置要请求的参数的控制器:
@GetMapping
public List<Car> getCars(@RequestParam(required = false) Integer minPrice,
@RequestParam(required = false) Integer maxPrice,
@RequestParam(required = false) String model)
return carService.getCars(minPrice, maxPrice, model);
这是汽车服务,我想做的事:
public List<Car> getCars(Integer minPrice, Integer maxPrice, String model)
return carRepository
.findAll()
.stream()
.filter(car ->
//if minPrice exists
car.getPrice() >= minPrice
&&
//if maxPrice exists
car.getPrice() <= maxPrice
&&
//if model exists
car.getModel().equals(model))
.collect(Collectors.toList());
我可以在控制器中设置@RequestParam (defaultValue = "something")
,但这是有问题的,因为我不知道“模型”字段的默认值是什么,因为每辆汽车都有不同的模型,我仍然必须按默认值过滤项目,并且它不是必需的,因为如果没有给出它,我不想对它做任何事情。
我还尝试将Optional<>
作为参数传递,然后在过滤函数中使用 if 语句和 ifPresent() 方法检查每个参数,但我不知道如何将它们组合在一起。
【问题讨论】:
一个简单的规则要遵循,不要在你的代码中做任何事情,数据库比你做得更好。过滤和排序由数据库更好地处理。 @b.GHILAS 因此,您建议在存储库中创建例如 3 个 SQL 查询,然后在 getCars() 函数中编写 3 个 if 语句,检查参数是否存在并在其中执行正确的函数?因为我不知道如何使给定参数的所有配置在这些查询中起作用,因为其中一些肯定具有共同的元素。请您详细解释一下吗? 更新您的问题并提供实体 Car,我假设您希望默认获取所有汽车,并且如果有任何请求参数过滤器。如果这是您想要的,那么使用 JPA 很容易实现。 @b.GHILAS 我更新了它,是的,这正是我想要做的。 @b.GHILAS 是正确的。不要获取服务中的所有值和过滤器。将默认值设置为*
并将值传递给您的 @Repository
以用于参数化查询(以避免 SQL 注入攻击)。
【参考方案1】:
您可以像这样创建一个 jpa 查询(在您的汽车存储库中):
@Query("select c from Car c where (?1 is null or c.price >= ?1) and (?2 is null or c.price <= ?2) and (?3 is null or c.model = ?3)")
List<Car> getCars(Integer minPrice, Integer maxPrice, String model);
然后从您的CarService
调用它:
public List<Car> getCars(Integer minPrice, Integer maxPrice, String model)
return carRepository.getCars(minPrice, maxPrice, model);
在 postgresql 中规避强制转换问题的一种方法是使用参数的默认值。假设您将 0 设置为最低价格和最高价格的默认值以及模型的空字符串。
@Query("select c from Car c where (?1 = 0 or c.price >= ?1) and (?2 = 0 or c.price <= ?2) and (?3 = '' or c.model = ?3)")
List<Car> getCars(Integer minPrice, Integer maxPrice, String model);
在你的控制器中:
@RequestParam(defaultValue="") String model
@RequestParam(defaultValue="0") Integer minPrice
@RequestParam(defaultValue="0") Integer maxPrice
【讨论】:
不幸的是,我收到错误:,,ERROR: 运算符不存在:整数 >= bytea 提示:没有运算符与给定的名称和参数类型匹配。您可能需要添加显式类型转换。” @77jt777 更新了答案 它现在工作正常,它没有显示错误,但是当我发送请求时它返回响应代码 200 但我没有得到任何结果(没有显示任何汽车) @77jt777 默认值配置好了吗,生成的查询是什么? 这是我在控制台中唯一得到的:休眠:选择 car0_.id 作为 id1_0_,car0_.brand 作为brand2_0_,car0_.color 作为 color3_0_,car0_.customer 作为 customer7_0_,car0_.model 作为 model4_0_ , car0_.price as price5_0_, car0_.year_of_production as year_of_6_0_ from cars car0_ where (?=0 or car0_.price>=?) and (?=0 or car0_.price以上是关于如果给定@RequestParameter,则按其值过滤,如果没有,则不执行任何操作[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Java按整数字段对对象数组进行排序,如果它们相同,则按另一个整数值排序
python 排序 sorted 如果第一个条件 相同 则按第二个条件排序