【问题分类】中间件兼容 / JDBC集成异常

【关键词】JDBC、BeetISQL、batchInsert、RETURN_GENERATED_KEYS、rowid、类型转换异常
image.png

一、问题现象

某项目中集成 BeetISQL 2.13.8.RELEASE 版本,在通过 API 调用批量插入接口(batchInsert)并希望自动回填数据库生成的 sequence 值时,出现如下异常:

autoAssignKey failure

该错误会直接中断业务流程,使得批量插入操作无法正常获取数据库生成的主键 ID。

二、场景说明

目标表结构:

create table test_entity (
tid number primary key not null,
tname varchar2(30)
);
create sequence seq_tid;
Java Bean 示例(TestTable):

class TestTable {
private Long tid;
private String tname;
}

插入逻辑: 通过 batchInsert(List) 批量插入数据,其中 tid 字段由数据库 sequence 自动生成,未在 Java Bean 中提前赋值。

三、问题根因分析

现象定位:

在 BeetISQL 2.x 中,底层 JDBC 使用如下方式构建 PreparedStatement:
conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
此时未明确指定返回哪一列的 key。

实际效果:

YashanDB 的 JDBC 驱动会默认返回 ROWID(为字符串类型);

而业务中的 tid 字段为 NUMBER 类型;

导致中间件在将 ROWID 赋值给 tid 时,因类型不匹配(String → Long)触发异常。

四、适用版本

与 YashanDB 驱动版本无关;

主要影响 BeetISQL 2.x 系列版本;

BeetISQL 3.x 已修复此问题。

五、解决方案

方法一(推荐):升级至 BeetISQL 3.x

BeetISQL 3 中已修复此问题:

conn.prepareStatement(sql, this.getKeyHolderCols(holder, entity.getClass()));

可正常返回指定列的 sequence.nextval 值,类型转换无误。

方法二:禁用自动主键赋值(适用于 BeetISQL 2.x)

在调用 insertBatch() 时,将 autoAssignKey 参数设置为 false:


sqlManager.insertBatch(TestTable.class, dataList, false);

这样可以避免中间件自动尝试获取返回主键值,规避类型转换异常。

六、测试与验证过程

通过构造如下 SQL 模拟操作:


insert into TEST_ENTITY (tid, tname) values (seq_tid.nextval, ?)
returning rowid into ?

实际调试中可观察到返回的 rowid 类型为字符串,触发 autoAssignKey failure 的栈信息位于 key 映射阶段。

七、总结与建议
image.png

附:官方测试样例

beetlsql_2_demo(关闭自动返回主键)

beetlsql_3_demo(支持自动返回主键)


数据库砖家
1 声望0 粉丝