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

Spring Data JDBC派生批量删除查询运行报错问题咨询

Spring Data JDBC 2.3.5 非主键条件批量删除派生查询异常问题

问题复现场景

  • 自定义Repository继承CrudRepository<Customer, Long>,定义派生删除方法,期望删除所有匹配指定businessId的实体。businessId是非主键、允许重复值的非唯一列,单个值可对应多条数据记录。
  • 测试逻辑:先持久化2条businessId相同的Customer记录,再调用如下Repository方法:
fun deleteAllByBusinessId(businessId: Long)
  • 调用后抛出异常:
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 2

    at org.springframework.dao.support.DataAccessUtils.nullableSingleResult(DataAccessUtils.java:100)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.queryForObject(NamedParameterJdbcTemplate.java:244)

从异常栈可以确认,框架执行删除前先按条件查询单条匹配实体,实际命中2条导致报错,需要确认2.3.5版本是否对这类批量删除派生查询存在支持缺陷。

问题根因

该问题属于Spring Data JDBC 2.3.5版本的已知实现缺陷。
2.3.x版本分支中,派生删除方法的解析逻辑没有正确识别deleteAllByXXX的批量操作语义:无论方法名是否携带All关键字,框架都会默认按单实体删除逻辑处理,先调用queryForObject拉取唯一匹配的实体对象,再执行单条删除操作。只要查询条件命中记录数超过1,就会抛出上述结果集大小不匹配的异常。
该逻辑问题在3.0.0及以上正式版本中才被修复,2.3.x作为旧维护分支没有合入该逻辑调整。

2.3.5版本兼容解决方案

  • 方案1:手动编写自定义删除SQL,绕开派生查询的解析缺陷:
@Modifying
@Query("DELETE FROM customer WHERE business_id = :businessId")
fun deleteAllByBusinessId(businessId: Long)
  • 方案2:拆分查询+批量删除两步执行,使用Repository自带的批量删除方法:
// 先在Repository中定义条件查询方法
fun findAllByBusinessId(businessId: Long): List<Customer>

// 业务逻辑中执行删除
val matchCustomers = customerRepository.findAllByBusinessId(targetBusinessId)
customerRepository.deleteAll(matchCustomers)

内容的提问来源于stack exchange,提问作者user1100243

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:45:44