Spring Boot中JPA如何实现带可选参数的Delete删除查询
解决方案
你需要适配动态可选删除条件,有两种主流实现方案:
方案1:自定义@Query动态SQL(参数少的场景首选,实现最简单)
直接在Repository层通过@Query写带空值判断的删除语句,不需要额外引入其他依赖:
第一步:修改Repository层代码
@Transactional @Repository public interface ABCRepo extends CrudRepository<ABC, Long>{ // 原有方法保留 public List<ABC> findByABCIdAndStartYrAndStartMonth(String pilotId, int startYr, int startMonth); public long deleteABCByABCId(String pilotId); // 新增动态删除方法 @Modifying // 删改操作必须加该注解,让JPA识别这是写操作 @Query("DELETE FROM ABC a WHERE a.abcId = :abcId " + "AND (:bidYr IS NULL OR a.startYr = :bidYr) " + "AND (:bidMonth IS NULL OR a.startMonth = :bidMonth)") long deleteByDynamicConditions(String abcId, Integer bidYr, Integer bidMonth); }
逻辑说明:当可选参数为null时,对应条件段(:param IS NULL)会直接返回true,相当于不限制该字段,完美适配可选参数需求。
第二步:修正参数类型
把控制器层的bidYr、bidMonth从基本类型int改为包装类型Integer,否则前端不传参数时会被默认赋值为0,无法走空值判断逻辑。
方案2:JPA Criteria API(参数多、后续需扩展筛选条件的场景首选)
如果后续还要新增更多可选筛选条件,可以用Specification构造动态条件:
第一步:修改Repository继承接口
@Transactional @Repository public interface ABCRepo extends CrudRepository<ABC, Long>, JpaSpecificationExecutor<ABC> { // 原有方法保留 }
第二步:业务层(Biz层)构造动态删除逻辑
public long deleteDynamic(String abcId, Integer bidYr, Integer bidMonth) { Specification<ABC> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); // 必传条件 predicates.add(cb.equal(root.get("abcId"), abcId)); // 可选条件判断 if (bidYr != null) { predicates.add(cb.equal(root.get("startYr"), bidYr)); } if (bidMonth != null) { predicates.add(cb.equal(root.get("startMonth"), bidMonth)); } return cb.and(predicates.toArray(new Predicate[0])); }; // 查询符合条件的记录后批量删除 List<ABC> toDelete = abcRepo.findAll(spec); abcRepo.deleteAll(toDelete); return toDelete.size(); }
控制器层最终适配代码
修正你现有代码的语法错误,调用对应业务方法即可:
@RequestMapping(value="", method= RequestMethod.DELETE) public Response delete(@PathVariable("abc-id")String abcId, @RequestParam(name = "bid-yr", required = false) Integer bidYr, @RequestParam(name = "bid-month", required = false) Integer bidMonth) { LOGGER.info("Trying to delete pilot bank using abc id : {}, bidYr: {}, bidMonth: {}", abcId, bidYr, bidMonth); // 方案1调用:long deletedRecords = abcRepo.deleteByDynamicConditions(abcId, bidYr, bidMonth); // 方案2调用: long deletedRecords = abcBiz.deleteDynamic(abcId, bidYr, bidMonth); if(deletedRecords == 0) { throw new PilotNotFoundException("Entity not found "+abcId); } return Response.status(Response.Status.NO_CONTENT).entity(deletedRecords).build(); }
内容的提问来源于stack exchange,提问作者Lucifer Geralt
相关产品推荐
相关产品推荐

