ibatis和mybatis中的BatchExecutor
ibatis中的的处理方法
首先在你的dao中需要继承org.springframework.orm.ibatis.support.SqlMapClientDaoSupport
然后在代码中调用getSqlMapClientTemplate方法, 获取SqlMapClientTemplate对象,然后做处理
if (null == records || records.size() == 0) {
return;
}
// 执行回调
SqlMapClientTemplate sqlMapClientTemplate = iBatisDaoLS13.getSqlMapClientTemplate();
sqlMapClientTemplate.execute(new SqlMapClientCallback() {
// 实现回调接口
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
// 开始批处理, for循环里面的sql必须一致,否则会创建新的PreparedStatement
executor.startBatch();
for (Info info : records) {
executor.insert(NAMESPACE + "insertAInfo", info);
}
// 执行批处理
executor.executeBatch();
return null;
}
});
}
mybatis中的的处理方法
@Test
public void testJDBCBatch() throws SQLException {
String sql = "insert into t_user(name, mobile, email) values(?,?,?)";
try (Connection conn = dataSource.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql);) {
List<User> users = this.getUsers();
for (User user : users) {
pstmt.setString(1, user.getName());
pstmt.setString(2, user.getMobile());
pstmt.setString(3, user.getEmail());
pstmt.addBatch();
}
pstmt.executeBatch();
conn.commit();
}
}
在每一次调用的时候是调用Statement.addBatch()方法,最终所有的参数都传递完了,没有更多的参数时调用Statement.executeBatch()方法进行批量操作。在上一篇博文中我们查看了BatchExecutor的源码,它的核心代码doUpdate()方法,每次被调用的时候都是以handler.batch()结束,而handler.batch()对应的底层代码是调用对应的Statement的addBatch()方法。那它是在什么时候执行executeBatch()呢?
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
final Configuration configuration = ms.getConfiguration();
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
final BoundSql boundSql = handler.getBoundSql();
final String sql = boundSql.getSql();
final Statement stmt;
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
intlast = statementList.size() - 1;
stmt = statementList.get(last);
handler.parameterize(stmt);//fix Issues 322
BatchResult batchResult = batchResultList.get(last);
batchResult.addParameterObject(parameterObject);
} else {
Connection connection = getConnection(ms.getStatementLog());
stmt = handler.prepare(connection);
handler.parameterize(stmt); //fix Issues 322
currentSql = sql;
currentStatement = ms;
statementList.add(stmt);
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
// handler.parameterize(stmt);
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
它的executeBatch()是在doFlushStatements()方法调用中调用的,它会在当前Executor进行commit时调用,也会在当前Executor第一次执行doQuery()时调用,在这个时候都会调用Executor的flushStatements()方法,而BaseExecutor在执行flushStatements()时最终会调用其doFlushStatements()方法。当然,我们也可以手动的调用SqlSession的flushStatements()方法,其底层实现也会调用对应的BaseExecutor的flushStatements()方法。
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
try {
List<BatchResult> results = new ArrayList<BatchResult>();
if (isRollback) {
return Collections.emptyList();
}
for (int i = 0, n = statementList.size(); i < n; i++) {
Statement stmt = statementList.get(i);
BatchResult batchResult = batchResultList.get(i);
try {
batchResult.setUpdateCounts(stmt.executeBatch());
MappedStatement ms = batchResult.getMappedStatement();
List<Object> parameterObjects = batchResult.getParameterObjects();
KeyGenerator keyGenerator = ms.getKeyGenerator();
if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
} else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141
for (Object parameter : parameterObjects) {
keyGenerator.processAfter(this, ms, stmt, parameter);
}
}
} catch (BatchUpdateException e) {
StringBuilder message = new StringBuilder();
message.append(batchResult.getMappedStatement().getId())
.append(" (batch index #")
.append(i + 1)
.append(")")
.append(" failed.");
if (i > 0) {
message.append(" ")
.append(i)
.append(" prior sub executor(s) completed successfully, but will be rolled back.");
}
throw new BatchExecutorException(message.toString(), e, results, batchResult);
}
results.add(batchResult);
}
return results;
} finally {
for (Statement stmt : statementList) {
closeStatement(stmt);
}
currentSql = null;
statementList.clear();
batchResultList.clear();
}
}
下面是一个使用Mybatis的BatchExecutor进行批量操作的示例。在示例中我们创建了一个使用BatchExecutor的SqlSession,也可以是SqlSessionTemplate,其实现了SqlSession接口,底层通过一个SqlSession代理进行相应的操作。然后在循环中一次调用对应Mapper的新增操作,相当于调用BatchExecutor的doUpdate(),最后调用SqlSession的commit()方法提交事务,在SqlSession的commit()中会调用Executor的commit(),从而导致了executeBatch()的发生。
@Test
public void testExecutor() {
SqlSession session = this.sessionFactory.openSession(ExecutorType.BATCH);
UserMapper mapper = session.getMapper(UserMapper.class);
User user = null;
for (inti = 0; i < 10; i++) {
user = new User();
user.setName("Name_" + i);
user.setEmail("email");
mapper.insert(user);
}
// 批量插入User
session.commit();// 提交事务时批量操作才会写入数据库
session.close();
}
ibatis和mybatis中的BatchExecutor的更多相关文章
- xml中${}的使用含义(美元符号大括号,以Spring、ibatis、mybatis为例)
项目中,经常会在xml中看到这样的写法: <properties resource="properties/database.properties"/> <dat ...
- Mybatis中的拦截器
作者:moshenglv的专栏 拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法. ...
- Mybatis 中经典的 9 种设计模式!面试可以吹牛了
虽然我们都知道有23个设计模式,但是大多停留在概念层面,真实开发中很少遇到.Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式. Mybatis至少 ...
- Mybatis中9种经典的设计模式!你知道几个?
虽然我们都知道有23个设计模式,但是大多停留在概念层面,真实开发中很少遇到.Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式. Mybatis至少 ...
- Mybatis中 SIMPLE、REUSE、BATCH的区别
Executor分成两大类,一类是CacheExecutor,另一类是普通Executor. 普通类又分为: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情.它为每个语句的执行 ...
- ibatis 和 mybatis
ibatis 在daoImpl 层 继承 SqlMapClientDaoSupport 实现 dao 层的接口. this.getSqlMapClientTemplate().queryForObj ...
- IBatis 2.x 和 MyBatis 3.0.x 的区别(从 iBatis 到 MyBatis)
从 iBatis 到 MyBatis,你准备好了吗? 对于从事 Java EE 的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate.JPA 这样的一站式对象 / 关系 ...
- mybatis中foreach的用法(转)
foreach一共有三种类型,分别为List,[](array),Map三种. foreach属性 属性 描述 item 循环体中的具体对象.支持属性的点路径访问,如item.age,item.inf ...
- spring中@param和mybatis中@param使用差别
spring中@param /** * 查询指定用户和企业关联有没有配置角色 * @param businessId memberId * @return */ int selectRoleCount ...
随机推荐
- 简易计算器-leetcode
今天,开始在leetcode上面开始做题,第一个题目是: Implement a basic calculator to evaluate a simple expression string. Th ...
- JavaScript-checkbox标签-隐藏、显示、全选、取消和反选等操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Lua 截取字符串(截取utf-8格式字符串)
对utf-8完全没概念的可以看看我上一篇随笔:简单说说utf-8编码格式 另外,还要知道string.sub 和 string.byte 的用法. 先上完整代码: local StringHelper ...
- 编译程序遇到问题 relocation R_X86_64_32 against `.rodata' can not be used when making a shared object;
编译程序遇到问题 relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; 发现编译 ...
- 描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理
Session用于保存每个用户的专用信息. 每个客户端用户访问时,服务器都为每个用户分配一个唯一的会话ID(Session ID) . 她的生存期是用户持续请求时间再加上一段时间(一般是20分钟左右) ...
- jeesite表字段太多导致不能自动生成那张表的代码——————jetty 之 form too large | form too many keys 异常
看了Jetty的源码才发现,jetty限制了Form提交数据的大小,该源码类来自jetty lib库下的jetty-server-7.6.16.v20140903.jar包下的 org.eclipse ...
- Java注解【一、概述】
前面几篇Java学习笔记都是半夜写的,比较伤身体,今天开始想调整生物钟,早上起来学2小时,看看能坚持多久 本周目标: 1.JavaJDBC使用 2.JavaWeb编程 3.Java框架基础(反射+注解 ...
- 第十章、json和pickle模块
目录 第十章.json和pickle模块 一.序列化 二.json 三.pickle模块 第十章.json和pickle模块 一.序列化 把对象(变量)从内存中变成可存储或传输的过程称之为序列化, 序 ...
- 使用Django开发简单接口:文章增删改查
目录 1.一些准备工作 安装django 创建django项目 创建博客应用(app) 2.models.py 3.django admin 登录 创建超级用户 4.修改urls.py 5.新增文章接 ...
- zabbix监控项截图整理
general监控项