最近有个需求是需要在java 后端执行导入,数据量比较大, 需要对数据进行很多操作,最后要执行插入数据操作, 一开始先组织好插入数据的sql语句放在数组中,使用的是
jdbcTemplate.batchUpdate()
方法,后来发现当数据比较多 ,成千上万条时,他的插入效率比较慢,所以又改用了jdbc 的批量插入.插入速度有了很大的提速
方法1
直接使用了jdbctemplate内部封装的batchUpdate方法,他的底层也是用了 jdbc 的批量执行,但是执行效率要比 正常使用jdbc 批量执行要慢很多,插入2600条数据的20个字段左右的表用时40s 左右,
// sqls 为组织好的插入数据的sql数组,
//{"insert into user(id,name,pwd) values('1','a','123456')","insert into user(id,name,pwd) values('2','b','123456')",... }
// j
public void insertData(String[] sqls,JdbcTemplate jdbctemplate){
jdbctemplate.batchUpdate(sqls);
}
方法2
使用了 jdbc 的批量执行sql, 主要使用了addBatch(),executeBatch(),clearBatch()方法,
这样批量执行 大大的提高了执行效率,2600条数据 20个字段的表插入只用了4-5s,
下面方法控制每5000条sql执行一次,剩下不足500条最后再执行一次.
public void insertData2(String[] sqls,JdbcTemplate jdbctemplate){
Connection conn = jdbcTemplate.getDataSource().getConnenction();
conn.setAutoCommit(false);//设置连接对象的自动提交为false
Statement statement = conn.createStatement();
for(int i=0;i<sqls.length;i++){
statement.addBatch(sqls[i]);
if(i % 5000 ==0){
statement.executeBatch(); // 批量执行
conn.commit(); // 手动提交
statement.clearBatch(); // 清楚之前批量执行的
}
}
statement.executeBatch();
conn.commit();
statement.clearBatch();
}
注意:
- 数据库区别:
本项目用的是 oracle数据库, 而mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
?rewriteBatchedStatements=true
写在配置文件的url后面
作者:Nemo
- 可能出现的sql错误(本项目未遇到)
- Oracle数据库中打开的游标最大数为一定值,默认情况下是300,当代码到第二步时,循环中一个PreparedStatement占用了一个数据库游标,执行的循环超过这个数时就会产生游标数目溢出错误。
解决办法:每次执行完PreparedStatement,都将PreparedStatement.close()下,释放掉这个资源就好了
Exception in thread “main” java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01000: 超出打开游标的最大数
ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01000: 超出打开游标的最大数
ORA-01000: 超出打开游标的最大数 - java.sql.SQLException:ORA-00054;资源正忙,但指定以NOWAIT方式获取资源,或者超时失败
原因:数据库中存在未提交的记录 - java.sql.SQLException 索引中丢失in或out参数
原因:SQL语句有问题
解决:jdbc进行字段拼接插入操作时,为string类型的加上单引号
另外,用prepareStatement.setString(1, 字段值),可以防止字段值有单引号而破坏sql问题 - java.sql.BathUpdateException:ORA-01461;仅能绑定要插入LONG列的LONG值
原因:由于要插入的字段长度超出了数据库中表定义的字段长度
--------------------------补充-----------------------------------
varchar2是Oracle提供的特定数据类型
varchar2(10)一般情况最多存5个汉字,10个字符。具体要看数据库使用的字符集:GBK(汉字2字节;英文1个;Oracle安装默认GBK编码格式);UTF-8(汉字3字节,英文1个)
一般页面做输入字符串长度校验时,以数据库设计字段最大长度/3作为最大长度
nvarchar(10)可以存10个汉字,10个字符
当长度大于4000的时候就应该用CLOB,因为oracle的varchar2最多4000个字符 - ORA-24816:在实际的LONG或LOB列之后提供了扩展的非LONG绑定数据
原因:这个问题很奇怪,就算没有LONG类型的数据,全部都是VARCHAR2和CLOB在操作数据库更新的时候一直报这个错误
解决:歪打正着,调整了一下各种更新字段位置,将放在前面的CLOB类型放在后面,就不报错了