Spring Boot如何使用可选参数实现空参数自动忽略的搜索功能
Spring Boot 多可选参数分页搜索实现方案
针对JPA场景下多可选查询参数的动态搜索需求,最简便的实现方式是使用Spring Data JPA原生提供的Specification动态条件构造能力,自动忽略空值参数,无需拼接冗余SQL。
实现步骤
1. 扩展Repository接口
让你的InventoryRepository继承JpaSpecificationExecutor,获得动态查询执行能力:
public interface InventoryRepository extends JpaRepository<Inventory, Long>, JpaSpecificationExecutor<Inventory> { // 原有方法可保留 }
注:如果项目已经引入spring-boot-starter-data-jpa依赖,无需额外引入其他包即可使用该功能。
2. 改造Service层动态拼接查询条件
修改原有分页查询方法,接收所有可选搜索参数,仅当参数非空时才拼接对应查询条件:
@Override public Page<Inventory> listAllCarIfShow(int pageNumber, int pageSize, String name, String owner, String fuelType, String location, String insuranceValidity, String rto, Integer minPrice, Integer maxPrice) { Pageable pageable = PageRequest.of(pageNumber - 1, pageSize); Specification<Inventory> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); // 固定条件:仅查询展示状态的车辆,和原有逻辑一致 predicates.add(cb.equal(root.get("show"), true)); // 可选条件:参数非空时才拼接 if (name != null && !name.trim().isEmpty()) { // 名称模糊匹配,如需忽略大小写可统一转小写处理 predicates.add(cb.like(root.get("name"), "%" + name.trim() + "%")); } if (owner != null && !owner.trim().isEmpty()) { predicates.add(cb.like(root.get("owner"), "%" + owner.trim() + "%")); } if (fuelType != null && !fuelType.trim().isEmpty()) { predicates.add(cb.equal(root.get("fuelType"), fuelType.trim())); } if (location != null && !location.trim().isEmpty()) { predicates.add(cb.equal(root.get("location"), location.trim())); } if (insuranceValidity != null && !insuranceValidity.trim().isEmpty()) { predicates.add(cb.equal(root.get("insuranceValidity"), insuranceValidity.trim())); } if (rto != null && !rto.trim().isEmpty()) { predicates.add(cb.equal(root.get("rto"), rto.trim())); } // 价格区间筛选,可根据表单需求调整 if (minPrice != null) { predicates.add(cb.greaterThanOrEqualTo(root.get("price"), minPrice)); } if (maxPrice != null) { predicates.add(cb.lessThanOrEqualTo(root.get("price"), maxPrice)); } return cb.and(predicates.toArray(new Predicate[0])); }; return carInventoryRepository.findAll(spec, pageable); }
如果需要新增里程范围、车龄等其他筛选条件,按照相同逻辑在方法内追加判断即可。
3. 改造Controller层接收可选参数
将所有搜索参数设置为非必填,传入Service层,同时修正原有代码中分页参数写死的问题,增加搜索参数回显能力:
@GetMapping("/buy-car") public String showBuyCarPageList(Model model, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, @RequestParam(value = "name", required = false) String name, @RequestParam(value = "owner", required = false) String owner, @RequestParam(value = "fuelType", required = false) String fuelType, @RequestParam(value = "location", required = false) String location, @RequestParam(value = "insuranceValidity", required = false) String insuranceValidity, @RequestParam(value = "rto", required = false) String rto, @RequestParam(value = "minPrice", required = false) Integer minPrice, @RequestParam(value = "maxPrice", required = false) Integer maxPrice ){ int currentPage = page != null ? page : 1; int pageSize = size != null ? size : 16; Page<Inventory> pageObj = carInventoryService.listAllCarIfShow(currentPage, pageSize, name, owner, fuelType, location, insuranceValidity, rto, minPrice, maxPrice); model.addAttribute("currentPage", currentPage); model.addAttribute("totalPages", pageObj.getTotalPages()); model.addAttribute("totalItems", pageObj.getTotalElements()); model.addAttribute("carInfo", pageObj.getContent()); // 回传搜索参数用于前端表单回显 model.addAttribute("name", name); model.addAttribute("owner", owner); model.addAttribute("fuelType", fuelType); model.addAttribute("location", location); model.addAttribute("insuranceValidity", insuranceValidity); model.addAttribute("rto", rto); model.addAttribute("minPrice", minPrice); model.addAttribute("maxPrice", maxPrice); return "frontend/buy-car-list"; }
效果验证
改造完成后,你列出的三个请求场景都可以正常支持:
- 传name参数时,仅按名称筛选,其他空参数自动忽略
- 同时传name、owner参数时,叠加两个条件做精确筛选
- 传fuelType、owner参数时,按燃油类型和所有者叠加筛选
所有未传、值为空的参数都不会参与SQL条件拼接,完全符合可选搜索的需求。
优化建议
- 如果搜索参数较多,可以单独定义
InventorySearchDTO类封装所有搜索字段,Controller直接接收DTO对象,减少方法参数长度 - 字符串匹配建议增加大小写忽略逻辑,提升搜索体验
- 分页拼接时记得带上原有搜索参数,避免翻页后搜索条件丢失
内容的提问来源于stack exchange,提问作者Cipher
相关产品推荐
相关产品推荐

