使用MyBatis向Oracle插入数据遇ORA-01461错误求助
解决MyBatis批量插入Oracle时的ORA-01461错误
这个ORA-01461错误我之前在MyBatis+Oracle的批量插入场景下碰过好几次,核心原因说白了就是你插入的某个字段值长度超过了目标数据库列的定义,或者MyBatis参数类型和数据库列类型不匹配,导致Oracle把超长的字符串当成LONG类型处理,而目标列并不是LONG类型,所以抛出了这个绑定错误。下面是具体的排查和解决步骤:
第一步:排查数据库表列的定义
先去查CUS_ACTION_HISTORY_T表的字段类型和长度,比如用Oracle命令行执行:
DESC CUS_ACTION_HISTORY_T;
重点核对你插入的那些字段(比如REQUEST_ID、ENTITY_TYP等省略字段)的列属性:
- 如果是
VARCHAR2(n),确认你的插入值长度有没有超过n(Oracle 12c之前VARCHAR2最大支持4000字符,12c及之后可扩展到32767,但需要额外配置参数); - 确认没有把本该存入CLOB/LONG列的大文本内容,插到普通VARCHAR2列里。
第二步:检查MyBatis实体类和参数
打开你的com.dpworld.tos.admin.model.CusHistory实体类,逐一核对字段与数据库列的匹配度:
- 比如数据库列是
VARCHAR2(50),实体类对应字段是String没问题,但如果这个String字段存了超过50字符的内容,就会触发错误; - 批量插入时,检查列表中是否存在某个元素的字段值异常超长(比如某个
REQUEST_ID是几百甚至上千字符),这大概率是问题根源。
第三步:优化MyBatis批量插入的写法
很多时候批量插入的写法不当也会引发这个问题,比如循环执行单条INSERT、参数绑定方式错误等。推荐使用Oracle原生支持的UNION ALL批量插入写法,既高效又能避免参数绑定异常:
<insert id="insertCusHistoryData" parameterType="java.util.List"> INSERT INTO CUS_ACTION_HISTORY_T( SEQ_NO, GLOBAL_ID, REQUEST_ID, CUS_ACTION_CODE, CUS_REQUEST_TIME, ENTITY_TYP -- 补充其他需要插入的字段 ) SELECT SEQ_CUS_ACTION_HISTORY.NEXTVAL, t.* FROM ( <foreach collection="list" item="item" separator="UNION ALL"> SELECT #{item.globalId}, #{item.requestId}, #{item.cusActionCode}, #{item.cusRequestTime}, #{item.entityTyp} -- 补充对应实体类字段 FROM DUAL </foreach> ) t </insert>
这种写法把序列生成放在外层,避免循环调用序列的性能损耗,同时用参数绑定替代字符串拼接,能有效避免长度溢出问题。
第四步:处理大文本插入需求
如果你的字段内容本身就很长(比如超过4000字符),需要先把数据库列改成CLOB类型,然后在MyBatis映射中指定jdbcType:
#{item.longContent, jdbcType=CLOB}
这样MyBatis会正确将字符串绑定到CLOB列上,不会被Oracle识别为LONG类型。
内容的提问来源于stack exchange,提问作者salz
相关产品推荐
相关产品推荐

