SpringBoot中如何使用多个@RequestParam配合@Query实现数据查询
多@RequestParam参数核心逻辑
Spring MVC中@RequestParam负责将HTTP GET请求URL中?后拼接的查询键值对,按参数名匹配绑定到Controller方法的入参上。多个@RequestParam参数不需要额外特殊配置,仅需保证注解声明的参数名和请求传入的参数名一致即可,参数顺序不影响绑定结果。
现有代码的基础问题
当前代码存在3处直接导致功能不可用的错误:
- Repository层JPQL拼写错误:两个查询条件拼接处未留空格,拼接后SQL片段会变成
'%xxx%And e.salary'触发语法错误;同时e.salary > LIKE属于非法语法,比较运算符>和模糊查询关键字LIKE不能组合使用。 - Repository层方法入参不匹配:JPQL中定义了
:date、:salary两个命名参数,但方法仅声明了1个String类型入参,无法完成参数绑定。 - 层间参数透传缺失:Controller仅接收1个参数,Service层也只透传1个参数到Repository,缺少salary参数的全链路传递。
正确实现方式
按三层分别修正代码即可:
- 修正Repository层代码
首先修正JPQL语法,同时为方法入参加@Param注解显式绑定命名参数,注意salary为数值类型,常规场景下直接做数值比较即可,不需要用LIKE:
如果确实需要对salary做模糊匹配(比如匹配薪资数字包含某一片段的记录),需要先将数值字段转为字符串再做LIKE匹配:@Query("SELECT e FROM Employee e WHERE " + "e.startDate LIKE CONCAT('%', :date, '%') " + "AND e.salary > :salary") List<Employee> searchEmployees(@Param("date") String date, @Param("salary") BigDecimal salary);CAST(e.salary AS string) LIKE CONCAT('%', :salary, '%'),该写法会导致字段索引失效,非必要不使用。 - 修正Service层代码
同步调整Service方法签名,接收两个参数并透传到Repository:// Service接口方法定义 List<Employee> searchEmployees(String date, BigDecimal salary); // Service实现类方法 @Override public List<Employee> searchEmployees(String date, BigDecimal salary) { return employeeRepository.searchEmployees(date, salary); } - 修正Controller层代码
直接在方法入参中添加第二个@RequestParam注解声明salary参数,将两个参数一同传入Service方法即可:
接口调用时直接在URL后拼接两个查询参数即可,示例请求路径:@GetMapping(path="/search") public ResponseEntity<List<Employee>> searchEmployees( @RequestParam("date") String date, @RequestParam("salary") BigDecimal salary) { return ResponseEntity.ok(employeeService.searchEmployees(date, salary)); }/search?date=2024-01&salary=5000。
@Query命名参数绑定规则
Spring Data JPA中Repository方法入参与JPQL命名参数的绑定遵循以下规则:
- 显式绑定优先:如果入参添加了
@Param("xxx")注解,会直接将该参数值绑定到JPQL中名为:xxx的命名参数,和参数顺序、方法形参名无关。 - 默认名匹配:如果入参未添加
@Param注解,框架会直接用方法形参名和JPQL命名参数做精确匹配。该模式依赖编译时保留方法形参名(JDK8+需要开启-parameters编译参数),环境兼容性差,多参数场景建议始终使用@Param做显式绑定。 - 数量严格匹配:JPQL中定义的所有命名参数,必须有对应的绑定入参,缺少参数或多余参数都会导致项目启动时抛出绑定异常。
- 类型匹配:传入的参数类型需要和对应实体字段的类型兼容,比如数值类型字段不要直接传入非数字格式的字符串,日期字段要匹配对应日期类型或符合格式的字符串,否则会抛出类型转换异常。
内容的提问来源于stack exchange,提问作者RohanRider
相关产品推荐
相关产品推荐

