最近在项目中需要一次性插入大批量数据到数据库,如果使用传统for循环方式一条记录一条记录地插入显然效率太低,而且大大增加了数据库的开销,因为每执行一次insert操作都要创建一次数据库连接。于是,想到了ibatis的批处理方法。
网上找了很多资料,大同小异,总结了一下,主要有一下两种方式:
xml代码如下:
"insertData" parameterClass="java.util.List">
insert into batchinsert_test(id,
studentid,
schoolid,
schoolname,
supplierid,
countryid,
major,
payerid,
schinesename,
senglishsurname
)
select hibernate_sequence.nextval, t.* from ( // 使用序列生成主键
" union all " > // conjunction属性表示每次循环结束添加的字符
select
#list[].studentid#, // list为传入的参数名称
#list[].schoolid#,
#list[].schoolname#,
#list[].supplierid#,
#list[].countryid#,
#list[].major#,
#list[].payerid#,
#list[].schinesename#,
#list[].senglishsurname#
from dual
) t
注意:此语法只支持Oracle,不支持mysql,mysql的自行百度,原理是一样的,只是语法不一样
调用代码如下:
@Override
public void insertData(List list) {
try {
this.sqlMapClient.insert("OrderformImport.insertData", list);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
测试发现,使用xml拼接sql的方式实现批量插入数据有一个问题,当批量插入的数据量太大(我的是超过5000条数据),会报“无效的主机/绑定变量名”异常,原因未明,还望知道的大神不吝赐教,楼主不胜感激。
ibatis通过sqlMapClient提供了一组方法用于实现批处理:
为了避免事务代码的入侵,把事务完全交给Spring统一处理,我们使用Spring的回调模式去实现:
首先你的dao需要继承SqlMapClientDaoSupport类,或者在你的dao中将sqlMapClient注入到sqlMapClientTemplate中,然后调用sqlMapClientTemplate的execute方法,覆写SqlMapClientCallback类中的doInSqlMapClient方法
@Repository("testDao")
public class TestDaoImpl extends SqlMapClientDaoSupport implements TestDao {
@Override
public void insertBatchData(final List list) {
// list入参必须声明为final,不能被修改
// 执行回调
getSqlMapClientTemplate().execute(new SqlMapClientCallback
最终可能抛出的异常:DataAccessException
id="insertData2" parameterClass="com.iss.itreasury.cbeservice.transaction.orderformimport.web.batchInsertEntity">
"Long" type="pre" keyProperty="id">
select hibernate_sequence.nextval from dual
insert into batchinsert_test(id,
studentid,
schoolid,
schoolname,
supplierid,
countryid,
major,
payerid,
schinesename,
senglishsurname
)
values(#id#,
#studentid#,
#schoolid#,
#schoolname#,
#supplierid#,
#countryid#,
#major#,
#payerid#,
#schinesename#,
#senglishsurname#
)
测试了10万条数据,导入正常,耗时大概4分钟多点,在实际项目中,如果数据量大,建议每1000条(这个根据自己的实际情况自己定)就做一次批量导入,这样效率会比一次性批量导入高很多。