http://lililucky1211.iteye.com/blog/1726187
Ibatis中进行批量操作(转)
iBatis整理——iBatis批处理实现(Spring环境)
http://www.cnblogs.com/sunwei2012/archive/2010/11/26/1888497.html
大概是太久没有写Dao了,这部分真的忘得太干净了。
从4个层面分析这部分实现:
- iBatis的基本实现
- 基于事务的iBatis的基本实现
- 基于事务的Spring+iBatis实现
- 基于回调方式的Spring+iBatis实现
1.iBatis的基本实现
iBatis通过SqlMapClient提供了一组方法用于批处理实现:
- startBatch() 开始批处理
- executeBatch() 执行批处理
代码如下:
- public void create(List<Reply> replyList) {
- try {
- // 开始批处理
- sqlMapClient.startBatch();
- for (Reply reply: replyList) {
- // 插入操作
- sqlMapClient.insert("Reply.create", reply);
- }
- // 执行批处理
- sqlMapClient.executeBatch();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
这是基于iBatis的最基本实现,如果你一步一步debug,你会发现:其实,数据库已经执行了插入操作!
因此,除了这两个核心方法外,你还需要开启事务支持。否则,上述代码只不过是个空架子!
2.基于事务的iBatis的基本实现
事务处理:
- startTransaction() 开始事务
- commitTransaction() 提交事务
- endTransaction() 结束事务
我们以insert操作为例,把它们结合到一起:
- public void create(List<Reply> replyList) {
- try {
- // 开始事务
- sqlMapClient.startTransaction();
- // 开始批处理
- sqlMapClient.startBatch();
- for (Reply reply: replyList) {
- // 插入操作
- sqlMapClient.insert("Reply.create", reply);
- }
- // 执行批处理
- sqlMapClient.executeBatch();
- // 提交事务
- sqlMapClient.commitTransaction();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- // 结束事务
- sqlMapClient.endTransaction();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
replyList是一个List,要把这个List插入到数据库,就需要经过这三个步骤:
- 开始批处理 startBatch()
- 插入 insert()
- 执行批处理 executeBatch()
如果要在Spring+iBatis中进行批处理实现,需要注意使用同一个sqlMapClient!同时,将提交事务的工作交给Spring统一处理!
3.基于事务的Spring+iBatis实现
- public void create(List<Reply> replyList) {
- if (!CollectionUtils.isEmpty(replyList)) {
- // 注意使用同一个SqlMapClient会话
- SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();
- try {
- // 开始事务
- sqlMapClient.startTransaction();
- // 开始批处理
- sqlMapClient.startBatch();
- for (Reply reply : replyList) {
- // 插入操作
- sqlMapClient.insert("Reply.create", reply);
- }
- // 执行批处理
- sqlMapClient.executeBatch();
- // 提交事务 交给Spring统一控制
- // sqlMapClient.commitTransaction();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- // 结束事务
- sqlMapClient.endTransaction();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
注意使用同一个sqlMapClient:
SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();
如果直接sqlMapClientTemplate执行insert()方法,将会造成异常!
想想,还有什么问题?其实问题很明显,虽然解决了批处理实现的问题,却造成了事务代码入侵的新问题。 这么做,有点恶心!
除此之外,异常的处理也很恶心,不能够简单的包装为 DataAccessException 就无法被Spring当作统一的数据库操作异常做处理。
4.基于回调方式的Spring+iBatis实现
如果观察过Spring的源代码,你一定知道,Spring为了保持事务统一控制,在实现ORM框架时通常都采用了回调模式,从而避免了事务代码入侵的可能!
修改后的代码如下:
- @SuppressWarnings("unchecked")
- public void create(final List<Reply> replyList) {
- // 执行回调
- sqlMapClientTemplate.execute(new SqlMapClientCallback() {
- // 实现回调接口
- public Object doInSqlMapClient(SqlMapExecutor executor)
- throws SQLException {
- // 开始批处理
- executor.startBatch();
- for (Reply reply : replyList) {
- // 插入操作
- executor.insert("Reply.create", reply);
- }
- // 执行批处理
- executor.executeBatch();
- return null;
- }
- });
- }
注意,待遍历的参数replyList需要加入final标识!即,待遍历对象不能修改!
这样做,就将事务处理的控制权完全交给了Spring!
简述:
- SqlMapClientCallback 回调接口
- doInSqlMapClient(SqlMapExecutor executor) 回调实现方法
- DataAccessException 最终可能抛出的异常
http://michael-softtech.iteye.com/blog/620433
最近遇到这样一个客户需求:需要向数据库里面一次插入几万条数据。系统的Persistence层用的是ibatis,
事务是通过spring管理。之前都是少量数据的操作,所以都是按照以下方式插入的:
- class Service extends SqlMapClientDaoSupport
- {
- public void insert(...)
- {
- getSqlMapClientTemplate().insert(..);
- }
- }
但是数据量大时,速度奇慢。于是找时间读了一下ibatis的源码,终于发现了问题所在,记录如下:
首先,过跟踪代码,发现sql的相关操作都有这样一个入口:
- public Object execute(SqlMapClientCallback action){ action.doInSqlMapClient(session);....}
上面的session是SqlMapSession的一个实例,而SqlMapSession继承了SqlMapExecutor接口,实际上以上的代码最终还是通过SqlMapExecutor的对应方法来实现(比如:session.insert(..)).
于是继续追踪SqlMapSession的实现类:SqlMapSessionImpl。发现这个类的所有JDBC操作都是通过代理类SqlMapExecutorDelegate来实现的(这个代理类比SqlExecutor多了事务管理的配置:有一个TransactionManager)。这个代理类在每个单独的操作时,都先有这样一条语句:
- trans = getTransaction(session);
- autoStart = trans == null;
- trans = autoStartTransaction(session, autoStart, trans);
上述代码通过判断sutoStart来决定是不是开启一个事务。而autoStart是通过判断当前是不是已经有打开的事务
来赋值的。那么就可以理解了:如果当前操作没有在事务下面,那么自动开启(取出)一个事务;如果已经有了事务,那么 直接使用当前事务。如果要进行批量操作,那么就必须在调用之前开启一个事务。所以就简单了:
- public Object operate(final List<CardInfo> cardsToAdd, final List<AcctInfo> acctsToAdd, final List<AcctInfo> acctsToUpdate) throws DataAccessException{
- Object obj=this.getSqlMapClientTemplate().execute(new SqlMapClientCallback(){
- public Object doInSqlMapClient(SqlMapExecutor executor)
- {
- try{
- getSqlMapClient().startTransaction();
- executor.startBatch();...
后面的startBatch语句是通过使用jdbc的批处理来提高效率。这样就能顺利执行同一个事务下的批量操作了(注意:如果在批量startBatch之前没有开启事务,批处理是无效的)。
相关推荐
ibatis批处理.doc ibatis批处理.doc
NULL 博文链接:https://san-yun.iteye.com/blog/900949
ibatis批量操作存在两种方式: 一种是直接在代码中进行循环操作,另一种是在配置文件中进行循环操作。
ibatis 完美例子 一对多 批处理 事务 和 spring struts2集成 ,一朵多 插入1万条数据,不到2秒,备注不包含类库
技术分享:ibatis的两种方式实现批处理
开发指南 iBATIS SQL Maps Page 3 of 62 Map类型的Result 复杂类型属性(即自定义类型的属性) 避免N+1 Select(1:1) 延迟加载 VS 联合查询(1:1) 复杂类型集合的属性 避免N+1 Select(1:M和M:N) 组合键值或多...
基本篇重点讲述了数据批处理的核心概念、典型的作业配置、作业步配置,以及Spring Batch框架中经典的三步走策略:数据读、数据处理和数据写,详尽地介绍了如何对CVS格式文件、JSON格式文件、XML文件、数据库和JMS...
SQL Maps (com.ibatis.sqlmap.*)......................................................................................................5 SQL Map的概念........................................................
完完全全可以用的,放心下载! 1、日期控件 ...5、jdbc 批处理 sql 6、各种数据库的分页方法 7、数据库的优化 8、海量数据的处理 9、sql 注入 10、java 设计模式 11、iBatis 使用 12、webservice 13、Hessian
使用eGovframework,maven,ibatis开发 TCP侦听器,TCP处理程序功能实现 实现专业的解析功能 响应代码,州代码设计和实施 FTP通讯功能实现 传统数据删除批处理功能的实现 常见异常功能的实现 Admin Manager的页面...
自动生成dto\dao\xml 自带批处理自动生成程序
自己整理的一位牛人写的通向架构师的道路的博文,对架构师入门很有指导意义,列出章节如下: (第一天)之Apache整合Tomcat ...(第三天)之apache性能调优 ...(第二十七天)IBM网格计算与企业批处理任务架构