有的时候需要一次性执行大批量的SQL,而不是执行一条SQL向数据库提交一次,那么会
用到 IBATIS 的batch提交。
IBATIS的 batch提交也是基于 JDBC的batch功能。
那么我现来写段代码示范一下:
第一步,建立我的测试类。
其中 BabyDO,sexEnum 等类是自己写的,并不重要,只要让程序跑起来,读者可以自己写下。不多讲了,主要讲重点的几个语句。
package com.yajun;
// import 很多JDK给的类
import com.yajun.dataobject.BabyDO;
import com.yajun.enumdemo.SexEnum;
import com.yajun.impl.BabyDAOImpl;
/**
* 专门测试batch操作的
*
* @author yajun
*
*/
public class BatchInsertTest {
private BabyDAOImpl babyDAO = new BabyDAOImpl();
public static void main(String[] args) throws SQLException {
BatchInsertTest test = new BatchInsertTest();
test.insertBaby();
}
// 批量插入婴儿并且插入数据库
private void insertBaby() throws SQLException {
List<BabyDO> babys = new ArrayList<BabyDO>();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
BabyDO baby = new BabyDO();
baby.setName("乌鸦军");
baby.setSex(SexEnum.Male);
baby.setBirthday(new Date());
baby.setHobby("踢寂寞足球");
baby.setAge(i);
babys.add(baby);
}
int count = babyDAO.insertBatch(babys);
long end = System.currentTimeMillis();
System.out.println("============ 成功插入BABY " + count + "条 =============");
System.out.println("消费时间 " + (end - start));
}
}
第二步,建立BabyDAO的实现类BabyDAOImpl
package com.yajun.impl;
// import 很多JDK给的类
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.yajun.dao.BabyDAO;
import com.yajun.dataobject.BabyDO;
import com.yajun.dataobject.BabyTestDO;
public class BabyDAOImpl implements BabyDAO {
private SqlMapClient client;
public BabyDAOImpl() {
try {
Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
client = SqlMapClientBuilder.buildSqlMapClient(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
……(省略其他方法)
/**
* 批量添加小孩
*
* @param babys
* @return
* @throws SQLException
*/
public Integer insertBatch(List<BabyDO> babys) throws SQLException {
int count = 0;
try {
// 自己控制事物的开始
client.startTransaction();
client.startBatch();
for (BabyDO babyDO : babys) {
try {
client.insert("insert-baby", babyDO);
} catch (Exception e) {
System.out.println("插入婴儿失败");
}
}
count = client.executeBatch();
} finally {
// 自己控制事物的结束
client.endTransaction();
}
return count;
}
……(省略其他方法)
运行起来的结果:
============ 成功插入BABY 10000条 =============
消费时间 2610
可以看到插入10000条数据只需要2秒钟。
那么这里的关键点是我的注释:需要手工控制事物执行,否则事物会在第一条SQL insert 的时候自动将事物关闭掉。
具体原因的代码请看 IBATIS 源码(主要请注意我加注释的那几句话):
public Object insert(SessionScope sessionScope, String id, Object param) throws SQLException {
Object generatedKey = null;
MappedStatement ms = getMappedStatement(id);
Transaction trans = getTransaction(sessionScope);
// 如果trans为空的华autoStart=true;如果不手工控制事物,那么这里就是为空
boolean autoStart = trans == null;
try {
// 如果autoStart=true,开启事物
trans = autoStartTransaction(sessionScope, autoStart, trans);
SelectKeyStatement selectKeyStatement = null;
if (ms instanceof InsertStatement) {
selectKeyStatement = ((InsertStatement) ms).getSelectKeyStatement();
}
// Here we get the old value for the key property. We'll want it later if for some reason the
// insert fails.
Object oldKeyValue = null;
String keyProperty = null;
boolean resetKeyValueOnFailure = false;
if (selectKeyStatement != null && !selectKeyStatement.isRunAfterSQL()) {
keyProperty = selectKeyStatement.getKeyProperty();
oldKeyValue = PROBE.getObject(param, keyProperty);
generatedKey = executeSelectKey(sessionScope, trans, ms, param);
resetKeyValueOnFailure = true;
}
StatementScope statementScope = beginStatementScope(sessionScope, ms);
try {
ms.executeUpdate(statementScope, trans, param);
}catch (SQLException e){
// uh-oh, the insert failed, so if we set the reset flag earlier, we'll put the old value
// back...
if(resetKeyValueOnFailure) PROBE.setObject(param, keyProperty, oldKeyValue);
// ...and still throw the exception.
throw e;
} finally {
endStatementScope(statementScope);
}
if (selectKeyStatement != null && selectKeyStatement.isRunAfterSQL()) {
generatedKey = executeSelectKey(sessionScope, trans, ms, param);
}
// 如果autoStart为true自动提交事务(提交事务以后,后面的SQL就没有在一个BATCH里面了)
autoCommitTransaction(sessionScope, autoStart);
} finally {
autoEndTransaction(sessionScope, autoStart);
}
return generatedKey;
}
分享到:
相关推荐
iBatis Web用法实例工程
比较全面的介绍了Ibatis,是入门的比较经典的文档
ibatis入门与ibatis迭代的用法
iBATIS缓存的使用方法
ibatis学习 ibatis总结 ibatis ibatis ibatis
ibatis: dynamic 使用方法
ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料
ibatis demo,ibatis例子,ibatis示例
iBATIS 级联iBATIS 级联iBATIS 级联
ibatis3.0中in的用法ibatis3.0中in的用法ibatis3.0中in的用法ibatis3.0中in的用法
ibatis的原码 ibatis源码 ibatis源码 ibatis源码
ibatis
将NPetShop的例子下载好之后,由于原来是基于VS2003的版本,在本地用VS2005打开后编译、运行时有一些问题,主要问题和解决方法如下: 1、转换成VS2005的版本 a、直接打开NPetshop.sln文件,按提示一直点击"下一步...
Ibatis3,手册,Ibatis3手册,Ibatis3使用手册,Ibatis3参考手册
ibatis代码自动生成,ibatis代码自动生成,ibatis代码自动生成,ibatis代码自动生成
ibatis api,ibatis文档,ibatis说明文档
ibatis教程,ibatis帮助文档,ibatis学习入门
ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南ibatis2指南
简单的Ibatis入门例子,让你踏入Ibatis大门
” <br>但别犯愁:SQL本身具备了一些重要的功能,并且通过模板的使用,在Spring应用中采用iBATIS显得轻而易举。在此摘录中,两位作者将和你一起安装iBATIS并将其集成进你的Spring应用中。他们也阐明了怎样取得你...