MyBatis 批量插入包含 BLOB 类型的数据到 Oracle 异常问题分析
Posted 毕小宝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis 批量插入包含 BLOB 类型的数据到 Oracle 异常问题分析相关的知识,希望对你有一定的参考价值。
背景
本周项目开发过程中,有一个简单的批量插入附件到 Oracle 数据库的功能,DAO 编写测试期间都是用的小文件,BLOB 类型的字段插入正常。
真正联调测试时,上传的都是超过 4000 字节的文件,总是报下列异常:
Cause: java.sql.SQLException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
; uncategorized SQLException; SQL state [72000]; error code [1461]; ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
; nested exception is java.sql.SQLException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
本文记录这个问题的分析过程,作为网络笔记,以备后续查看!
问题排查
这是一个简单的批量插入,用的是 UNION ALL
:
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO FELE_ATTACHMENT(ID,ATTACHMENT,ATTACHMENT_NAME,ATTACHMENT_SIZE)
<foreach collection="list" item="tempData" index="index" separator="UNION ALL">
(SELECT
#tempData.id,jdbcType=VARCHAR,
#tempData.attachment,jdbcType=BLOB,
#tempData.attachmentName,jdbcType=VARCHAR,
#tempData.attachmentSize,jdbcType=DECIMAL
FROM DUAL
)
</foreach>
</insert>
起先以为是表中一个 Number
类型、存储文件长度字段的问题,去掉它后,插入还是报异常,但是实体字段用 byte[]
类型存储附件二进制流的思路是正确的。
把批量插入换成 MyBatis 的单条插入后,数据也能正常插入,所以确定问题还是在批量插入SQL 语句上。
最终确定了问题原因:批量将 byte[]
保存到 BLOB
字段时,不能使用 Union all
,因为它使用from dual
从虚表查询获取数据。
而从虚表取数据时,如果字段长度介于 2000-4000
之间时,Oracle 会将字段类型转为 Long
类型,原来如此。
问题修正
修改批量插入的方式,使用 begin end
连接批量插入语句:
<insert id="batchInsert" parameterType="java.util.List">
begin
<foreach collection="list" item="tempData" index="index" separator =";">
INSERT INTO FELE_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>
启示录
详情解决过程参考了 这篇文章,感谢网友的分享。
以上是关于MyBatis 批量插入包含 BLOB 类型的数据到 Oracle 异常问题分析的主要内容,如果未能解决你的问题,请参考以下文章