2024-09-30 08:58:14
本周项目开发过程中,有一个简单的批量插入附件到 Oracle 数据库的功能,DAO 编写测试期间都是用的小文件,BLOB 类型的字段插入正常。
真正联调测试时,上传的都是超过 4000 字节的文件,总是报下列异常:
Cause:java.sql.SQLException:ORA-01461:仅能绑定要插入LONG列的LONG值;uncategorizedSQLException;SQLstate[72000];errorcode[1461];ORA-01461:仅能绑定要插入LONG列的LONG值;nestedexceptionisjava.sql.SQLException:ORA-01461:仅能绑定要插入LONG列的LONG值本文记录这个问题的分析过程,作为网络笔记,以备后续查看!
问题排查这是一个简单的批量插入,用的是 UNION ALL :
<insertid="batchInsert"parameterType="java.util.List">INSERTINTOFELE_ATTACHMENT(ID,ATTACHMENT,ATTACHMENT_NAME,ATTACHMENT_SIZE)<foreachcollection="list"item="tempData"index="index"separator="UNIONALL">(SELECT#{tempData.id,jdbcType=VARCHAR},#{tempData.attachment,jdbcType=BLOB},#{tempData.attachmentName,jdbcType=VARCHAR},#{tempData.attachmentSize,jdbcType=DECIMAL}FROMDUAL)</foreach></insert>起先以为是表中一个 Number 类型、存储文件长度字段的问题,去掉它后,插入还是报异常,但是实体字段用 byte[] 类型存储附件二进制流的思路是正确的。
把批量插入换成 MyBatis 的单条插入后,数据也能正常插入,所以确定问题还是在批量插入SQL 语句上。
最终确定了问题原因:批量将 byte[] 保存到 BLOB 字段时,不能使用 Union all ,因为它使用from dual 从虚表查询获取数据。
而从虚表取数据时,如果字段长度介于 2000-4000 之间时,Oracle 会将字段类型转为 Long 类型,原来如此。
问题修正修改批量插入的方式,使用 begin end 连接批量插入语句:
<insertid="batchInsert"parameterType="java.util.List">begin<foreachcollection="list"item="tempData"index="index"separator=";">INSERTINTOFELE_ATTACHMENT(ID,ATTACHMENT,ATTACHMENT_NAME,ATTACHMENT_SIZE)VALUES(#{tempData.id,jdbcType=VARCHAR},#{tempData.attachment,jdbcType=BLOB},#{tempData.attachmentName,jdbcType=VARCHAR},#{tempData.attachmentSize,jdbcType=DECIMAL})</foreach>;end;</insert>参考文章www.cnblogs.com/zhuifenglang/p/13857152.html