`
liuguofeng
  • 浏览: 435879 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

ibatis 批处理

    博客分类:
  • Java
 
阅读更多

http://lililucky1211.iteye.com/blog/1726187

 

Ibatis中进行批量操作(转)

 

iBatis整理——iBatis批处理实现(Spring环境)

http://www.cnblogs.com/sunwei2012/archive/2010/11/26/1888497.html

最近做一个小项目,用到Spring+iBatis。突然遇到一个很久远,却很实在的问题:在Spring下怎么使用iBatis的批处理实现? 

大概是太久没有写Dao了,这部分真的忘得太干净了。 

从4个层面分析这部分实现: 
  1. iBatis的基本实现
  2. 基于事务的iBatis的基本实现
  3. 基于事务的Spring+iBatis实现
  4. 基于回调方式的Spring+iBatis实现


1.iBatis的基本实现 
iBatis通过SqlMapClient提供了一组方法用于批处理实现: 
  1. startBatch() 开始批处理
  2. executeBatch() 执行批处理

代码如下: 
Java代码 
  1. public void create(List<Reply> replyList) {  
  2.   
  3.     try {  
  4.         // 开始批处理  
  5.         sqlMapClient.startBatch();  
  6.   
  7.         for (Reply reply: replyList) {  
  8.             // 插入操作  
  9.             sqlMapClient.insert("Reply.create", reply);  
  10.         }  
  11.         // 执行批处理  
  12.         sqlMapClient.executeBatch();  
  13.   
  14.     } catch (Exception e) {  
  15.         e.printStackTrace();  
  16.     }  
  17. }  

这是基于iBatis的最基本实现,如果你一步一步debug,你会发现:其实,数据库已经执行了插入操作! 
因此,除了这两个核心方法外,你还需要开启事务支持。否则,上述代码只不过是个空架子! 

2.基于事务的iBatis的基本实现 
事务处理: 
  1. startTransaction() 开始事务
  2. commitTransaction() 提交事务
  3. endTransaction() 结束事务


我们以insert操作为例,把它们结合到一起: 
Java代码 
  1. public void create(List<Reply> replyList) {  
  2.   
  3.     try {  
  4.         // 开始事务  
  5.         sqlMapClient.startTransaction();  
  6.         // 开始批处理  
  7.         sqlMapClient.startBatch();  
  8.   
  9.         for (Reply reply: replyList) {  
  10.             // 插入操作  
  11.             sqlMapClient.insert("Reply.create", reply);  
  12.         }  
  13.         // 执行批处理  
  14.         sqlMapClient.executeBatch();  
  15.   
  16.         // 提交事务  
  17.         sqlMapClient.commitTransaction();  
  18.   
  19.     } catch (Exception e) {  
  20.         e.printStackTrace();  
  21.     } finally {    
  22.              try {  
  23.             // 结束事务  
  24.             sqlMapClient.endTransaction();  
  25.                 } catch (SQLException e) {  
  26.                          e.printStackTrace();  
  27.                      }  
  28.     }    
  29. }  

replyList是一个List,要把这个List插入到数据库,就需要经过这三个步骤: 
  1. 开始批处理 startBatch()
  2. 插入      insert()
  3. 执行批处理 executeBatch()

如果要在Spring+iBatis中进行批处理实现,需要注意使用同一个sqlMapClient!同时,将提交事务的工作交给Spring统一处理! 

3.基于事务的Spring+iBatis实现 
Java代码 
  1. public void create(List<Reply> replyList) {  
  2.     if (!CollectionUtils.isEmpty(replyList)) {  
  3.         // 注意使用同一个SqlMapClient会话  
  4.         SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient();  
  5.   
  6.         try {  
  7.             // 开始事务  
  8.             sqlMapClient.startTransaction();  
  9.             // 开始批处理  
  10.             sqlMapClient.startBatch();  
  11.             for (Reply reply : replyList) {  
  12.                 // 插入操作  
  13.                 sqlMapClient.insert("Reply.create", reply);  
  14.             }  
  15.   
  16.             // 执行批处理  
  17.             sqlMapClient.executeBatch();  
  18.             // 提交事务 交给Spring统一控制  
  19.             // sqlMapClient.commitTransaction();  
  20.   
  21.         } catch (Exception e) {  
  22.             e.printStackTrace();  
  23.         } finally {    
  24.                  try {  
  25.                 // 结束事务  
  26.                 sqlMapClient.endTransaction();  
  27.                     } catch (SQLException e) {  
  28.                              e.printStackTrace();  
  29.                          }  
  30.         }    
  31.     }  
  32. }  

注意使用同一个sqlMapClient: 
SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient(); 
如果直接sqlMapClientTemplate执行insert()方法,将会造成异常! 

想想,还有什么问题?其实问题很明显,虽然解决了批处理实现的问题,却造成了事务代码入侵的新问题。 这么做,有点恶心! 
除此之外,异常的处理也很恶心,不能够简单的包装为 DataAccessException 就无法被Spring当作统一的数据库操作异常做处理。 


4.基于回调方式的Spring+iBatis实现 
如果观察过Spring的源代码,你一定知道,Spring为了保持事务统一控制,在实现ORM框架时通常都采用了回调模式,从而避免了事务代码入侵的可能! 
修改后的代码如下: 
Java代码 
  1. @SuppressWarnings("unchecked")  
  2. public void create(final List<Reply> replyList) {  
  3.     // 执行回调  
  4.     sqlMapClientTemplate.execute(new SqlMapClientCallback() {  
  5.         // 实现回调接口  
  6.         public Object doInSqlMapClient(SqlMapExecutor executor)  
  7.                 throws SQLException {  
  8.             // 开始批处理  
  9.             executor.startBatch();  
  10.             for (Reply reply : replyList) {  
  11.                 // 插入操作  
  12.                 executor.insert("Reply.create", reply);  
  13.   
  14.             }  
  15.             // 执行批处理  
  16.             executor.executeBatch();  
  17.   
  18.             return null;  
  19.   
  20.         }  
  21.     });  
  22.   
  23. }  

注意,待遍历的参数replyList需要加入final标识!即,待遍历对象不能修改! 
引用
public void create(final List<Reply> replyList)

这样做,就将事务处理的控制权完全交给了Spring! 
简述: 
  1. SqlMapClientCallback 回调接口
  2. doInSqlMapClient(SqlMapExecutor executor) 回调实现方法
  3. DataAccessException 最终可能抛出的异常

http://michael-softtech.iteye.com/blog/620433

 

     最近遇到这样一个客户需求:需要向数据库里面一次插入几万条数据。系统的Persistence层用的是ibatis,

事务是通过spring管理。之前都是少量数据的操作,所以都是按照以下方式插入的:

 

 

Java代码   收藏代码
  1. class Service extends SqlMapClientDaoSupport  
  2. {  
  3.  public void insert(...)  
  4. {  
  5.   getSqlMapClientTemplate().insert(..);  
  6.     
  7. }  
  8.   
  9. }  

 

   但是数据量大时,速度奇慢。于是找时间读了一下ibatis的源码,终于发现了问题所在,记录如下:

 

   首先,过跟踪代码,发现sql的相关操作都有这样一个入口:

 

Java代码   收藏代码
  1. public Object execute(SqlMapClientCallback action){ action.doInSqlMapClient(session);....}  

 

      上面的session是SqlMapSession的一个实例,而SqlMapSession继承了SqlMapExecutor接口,实际上以上的代码最终还是通过SqlMapExecutor的对应方法来实现(比如:session.insert(..)).

      于是继续追踪SqlMapSession的实现类:SqlMapSessionImpl。发现这个类的所有JDBC操作都是通过代理类SqlMapExecutorDelegate来实现的(这个代理类比SqlExecutor多了事务管理的配置:有一个TransactionManager)。这个代理类在每个单独的操作时,都先有这样一条语句:

 

 

Java代码   收藏代码
  1.  trans = getTransaction(session);  
  2.  autoStart = trans == null;  
Java代码   收藏代码
  1. trans = autoStartTransaction(session, autoStart, trans);  

 

    上述代码通过判断sutoStart来决定是不是开启一个事务。而autoStart是通过判断当前是不是已经有打开的事务

     来赋值的。那么就可以理解了:如果当前操作没有在事务下面,那么自动开启(取出)一个事务;如果已经有了事务,那么  直接使用当前事务。如果要进行批量操作,那么就必须在调用之前开启一个事务。所以就简单了:

 

Java代码   收藏代码
  1. public Object operate(final List<CardInfo> cardsToAdd, final List<AcctInfo> acctsToAdd, final List<AcctInfo> acctsToUpdate) throws DataAccessException{  
  2.        
  3.   Object obj=this.getSqlMapClientTemplate().execute(new SqlMapClientCallback(){  
  4.      public Object doInSqlMapClient(SqlMapExecutor executor)  
  5.              {  
  6.        
  7.      try{  
  8.      getSqlMapClient().startTransaction();  
  9.      executor.startBatch();...  

   后面的startBatch语句是通过使用jdbc的批处理来提高效率。这样就能顺利执行同一个事务下的批量操作了(注意:如果在批量startBatch之前没有开启事务,批处理是无效的)。

分享到:
评论

相关推荐

    ibatis批处理.doc

    ibatis批处理.doc ibatis批处理.doc

    iBatis批处理

    NULL 博文链接:https://san-yun.iteye.com/blog/900949

    ibatis批处理

    ibatis批量操作存在两种方式: 一种是直接在代码中进行循环操作,另一种是在配置文件中进行循环操作。

    ibatis 完美例子 一对多 批处理 事务 和 spring struts2集成

    ibatis 完美例子 一对多 批处理 事务 和 spring struts2集成 ,一朵多 插入1万条数据,不到2秒,备注不包含类库

    ibatis的两种方式实现批处理.doc

    技术分享:ibatis的两种方式实现批处理

    iBatis SQL Maps开发指南.pdf

    开发指南 iBATIS SQL Maps Page 3 of 62 Map类型的Result 复杂类型属性(即自定义类型的属性) 避免N+1 Select(1:1) 延迟加载 VS 联合查询(1:1) 复杂类型集合的属性 避免N+1 Select(1:M和M:N) 组合键值或多...

    SpringBatch批处理 刘相编

    基本篇重点讲述了数据批处理的核心概念、典型的作业配置、作业步配置,以及Spring Batch框架中经典的三步走策略:数据读、数据处理和数据写,详尽地介绍了如何对CVS格式文件、JSON格式文件、XML文件、数据库和JMS...

    iBATIS 帮助文档

    SQL Maps (com.ibatis.sqlmap.*)......................................................................................................5 SQL Map的概念........................................................

    基于jsp的团购网站

    完完全全可以用的,放心下载! 1、日期控件 ...5、jdbc 批处理 sql 6、各种数据库的分页方法 7、数据库的优化 8、海量数据的处理 9、sql 注入 10、java 设计模式 11、iBatis 使用 12、webservice 13、Hessian

    TCPforScraping

    使用eGovframework,maven,ibatis开发 TCP侦听器,TCP处理程序功能实现 实现专业的解析功能 响应代码,州代码设计和实施 FTP通讯功能实现 传统数据删除批处理功能的实现 常见异常功能的实现 Admin Manager的页面...

    ibator1.2.1配置文件

    自动生成dto\dao\xml 自带批处理自动生成程序

    通向架构师的道路

    自己整理的一位牛人写的通向架构师的道路的博文,对架构师入门很有指导意义,列出章节如下: (第一天)之Apache整合Tomcat ...(第三天)之apache性能调优 ...(第二十七天)IBM网格计算与企业批处理任务架构

Global site tag (gtag.js) - Google Analytics