You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 17:15:03