在基于 Spring Boot + MyBatis-Plus + 达梦数据库(DM8) 的项目中,生产环境批量插入时偶现/必现报错:
dm.jdbc.driver.DMException: Invalid return into muti rows
// 中文驱动提示:RETURN INTO返回多行结果
该错误仅在批量插入 + 自增主键 + 返回主键场景触发,单条插入正常;本地/测试环境因驱动版本、配置差异,初期难以复现,导致问题排查受阻。
insertBatchSomeColumn(MP 内置批量插入,默认开启主键返回)DmJdbcDriver18.jar(本次测试v8.1.1.144)不支持批量插入时返回多条自增主键IDENTITY 自增主键,MP 自动生成 RETURNING id 语句MyBatis-Plus 的 insertBatchSomeColumn 默认开启 useGeneratedKeys=true,批量插入时会生成带 RETURNING 子句的 SQL:
INSERT INTO table (col1, col2) VALUES (?,?), (?,?) RETURNING id INTO ?
达梦旧驱动缺陷:不支持多行批量插入的 RETURNING 语法,仅支持单条返回,触发 Invalid return into muti rows 错误。
@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;
}
public interface NoticeCalculateErrorInfoMapper extends BaseMapper<NoticeCalculateErrorInfo> {
// 生产报错方法:MP内置批量插入(必报错)
void insertBatchSomeColumn(List<NoticeCalculateErrorInfo> list);
// 自定义批量方法(后续修复用)
void batchInsert(@Param("list") List<NoticeCalculateErrorInfo> list);
}
@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;
}
};
}
}
@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); // 正常执行
}
}
test_prod_insertBatchSomeColumn:必报错,提示 Invalid return into muti rowstest_my_batchInsert:正常执行,无报错允许升级驱动、需保留主键返回功能、快速修复。
DmJdbcDriver8.jar,2024 年第三季度版后命名规则变更)dmdbms/drivers/jdbc 下,匹配 JDK 版本(JDK8 选 DmJdbcDriver8.jar)insertBatchSomeColumn 不再报错,支持批量返回主键。无法升级驱动、需兼容旧环境、追求稳定。
关闭 useGeneratedKeys,禁用主键返回,绕过达梦旧驱动缺陷。
<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>
insertBatchSomeColumn 调用,替换为自定义 batchInsert| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 升级驱动 | 零代码修改、保留主键返回、根源修复 | 需升级驱动、需测试兼容性 | 允许驱动升级、需主键返回 |
| 自定义批量 | 稳定兼容、无依赖、快速上线 | 无法返回主键、需修改业务代码 | 无法升级驱动、旧环境兼容 |
选型建议:
达梦数据库 Invalid return into muti rows 错误,本质是旧版驱动不支持批量插入返回多行主键 + MyBatis-Plus 批量方法默认开启主键返回的兼容性问题。通过复现场景锁定根因,再结合升级驱动或自定义批量两种方案,可彻底解决该问题。
实际生产中,建议优先通过升级驱动从根源修复;若受限于环境,自定义批量插入(关闭主键返回) 是最稳妥的兼容方案,确保批量操作稳定运行。
如果以上方法都无法处理,可以考虑进行数据库升级。
文章
阅读量
获赞
