注册
达梦数据库批量插入报错 Invalid return into muti rows 问题(含复现+解决方案)
专栏/技术分享/ 文章详情 /

达梦数据库批量插入报错 Invalid return into muti rows 问题(含复现+解决方案)

mbj 2026/04/10 390 0 0
摘要

一、问题背景与现象

在基于 Spring Boot + MyBatis-Plus + 达梦数据库(DM8) 的项目中,生产环境批量插入时偶现/必现报错:

dm.jdbc.driver.DMException: Invalid return into muti rows
// 中文驱动提示:RETURN INTO返回多行结果

该错误仅在批量插入 + 自增主键 + 返回主键场景触发,单条插入正常;本地/测试环境因驱动版本、配置差异,初期难以复现,导致问题排查受阻。

二、根因深度分析

1. 核心触发条件(缺一不可)

  • MyBatis-Plus 批量方法:使用 insertBatchSomeColumn(MP 内置批量插入,默认开启主键返回)
  • 达梦旧版驱动DmJdbcDriver18.jar(本次测试v8.1.1.144)不支持批量插入时返回多条自增主键
  • 自增主键表:表含 IDENTITY 自增主键,MP 自动生成 RETURNING id 语句
  • 批量操作:一次插入 ≥2 条数据,驱动无法处理多行返回结果

2. 原理机制

MyBatis-Plus 的 insertBatchSomeColumn 默认开启 useGeneratedKeys=true,批量插入时会生成带 RETURNING 子句的 SQL:

INSERT INTO table (col1, col2) VALUES (?,?), (?,?) RETURNING id INTO ?

达梦旧驱动缺陷:不支持多行批量插入的 RETURNING 语法,仅支持单条返回,触发 Invalid return into muti rows 错误。

三、问题复现(关键代码+步骤)

1. 环境准备

  • JDK 1.8、Spring Boot 2.7.x、MyBatis-Plus 3.5.3.1
  • 达梦 8 数据库、旧版驱动(DmJdbcDriver18.jar,8.1.2 及以下)
  • 实体类(含自增主键):
@Data @TableName("notice_calculate_error_info") public class NoticeCalculateErrorInfo { @TableId(type = IdType.AUTO) private Long id; // 自增主键 private String calculateId; private String noticeId; private LocalDateTime createTime; }

2. Mapper 接口(关键)

public interface NoticeCalculateErrorInfoMapper extends BaseMapper<NoticeCalculateErrorInfo> { // 生产报错方法:MP内置批量插入(必报错) void insertBatchSomeColumn(List<NoticeCalculateErrorInfo> list); // 自定义批量方法(后续修复用) void batchInsert(@Param("list") List<NoticeCalculateErrorInfo> list); }

3. MP 配置(注入批量方法)

@Configuration public class MyBatisPlusConfig { @Bean public ISqlInjector sqlInjector() { return new DefaultSqlInjector() { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) { List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo); methodList.add(new InsertBatchSomeColumn()); // 注入报错方法 return methodList; } }; } }

4. 测试类(复现核心)

@SpringBootTest public class DemoTest { @Resource private NoticeCalculateErrorInfoMapper mapper; // 【测试1:生产同款,必报错】 @Test public void test_prod_insertBatchSomeColumn() { System.out.println("===== 执行生产批量:insertBatchSomeColumn ====="); List<NoticeCalculateErrorInfo> list = new ArrayList<>(); for (int i = 0; i < 7; i++) { // 模拟生产批量7条 NoticeCalculateErrorInfo info = new NoticeCalculateErrorInfo(); info.setCalculateId("CAL-TEST-001"); info.setNoticeId("NOTICE-001"); info.setCreateTime(LocalDateTime.now()); list.add(info); } mapper.insertBatchSomeColumn(list); // 触发报错 } // 【测试2:自定义方法,不报错】 @Test public void test_my_batchInsert() { System.out.println("===== 执行自定义批量:batchInsert ====="); List<NoticeCalculateErrorInfo> list = new ArrayList<>(); for (int i = 0; i < 7; i++) { NoticeCalculateErrorInfo info = new NoticeCalculateErrorInfo(); info.setCalculateId("CAL-001"); info.setNoticeId("N-001"); info.setCreateTime(LocalDateTime.now()); list.add(info); } mapper.batchInsert(list); // 正常执行 } }

5. 复现结果

  • test_prod_insertBatchSomeColumn必报错,提示 Invalid return into muti rows
  • test_my_batchInsert:正常执行,无报错

四、解决方案

方案一:升级达梦驱动(推荐,无代码侵入)

1. 适用场景

允许升级驱动、需保留主键返回功能、快速修复。

2. 操作步骤

  1. 替换驱动:使用达梦 8.1.4 及以上新版驱动(如本次测试8.1.4.200,DmJdbcDriver8.jar,2024 年第三季度版后命名规则变更)
  2. 驱动获取:达梦安装目录 dmdbms/drivers/jdbc 下,匹配 JDK 版本(JDK8 选 DmJdbcDriver8.jar
  3. 验证:替换后重新运行测试,insertBatchSomeColumn 不再报错,支持批量返回主键。

3. 优势

  • 零代码修改,直接兼容原有 MP 批量方法
  • 保留主键返回功能,不影响业务逻辑

方案二:自定义批量插入(稳定兼容,无需升级驱动)

1. 适用场景

无法升级驱动、需兼容旧环境、追求稳定。

2. 核心原理

关闭 useGeneratedKeys,禁用主键返回,绕过达梦旧驱动缺陷。

3. 实现步骤

  1. Mapper XML 配置(关键):
<insert id="batchInsert" useGeneratedKeys="false"> INSERT INTO notice_calculate_error_info ( calculate_id, notice_id, create_time ) VALUES <foreach collection="list" item="item" separator=","> (#{item.calculateId}, #{item.noticeId}, #{item.createTime}) </foreach> </insert>
  1. 业务代码替换:将生产中 insertBatchSomeColumn 调用,替换为自定义 batchInsert
  2. 验证:运行测试,批量插入正常执行,无报错

4. 优势

  • 兼容旧版驱动,无版本依赖

五、方案对比与选型建议

方案 优点 缺点 适用场景
升级驱动 零代码修改、保留主键返回、根源修复 需升级驱动、需测试兼容性 允许驱动升级、需主键返回
自定义批量 稳定兼容、无依赖、快速上线 无法返回主键、需修改业务代码 无法升级驱动、旧环境兼容

选型建议

  • 新项目/可升级:优先升级驱动,彻底解决问题
  • 旧项目/生产稳定:选择自定义批量,安全无风险

六、总结

达梦数据库 Invalid return into muti rows 错误,本质是旧版驱动不支持批量插入返回多行主键 + MyBatis-Plus 批量方法默认开启主键返回的兼容性问题。通过复现场景锁定根因,再结合升级驱动自定义批量两种方案,可彻底解决该问题。

实际生产中,建议优先通过升级驱动从根源修复;若受限于环境,自定义批量插入(关闭主键返回) 是最稳妥的兼容方案,确保批量操作稳定运行。

如果以上方法都无法处理,可以考虑进行数据库升级。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服