`

ibatis 批处理

 
阅读更多

 

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

    尽管Spring已经配置了事务管理,但在实际使用iBATIS批处理时,仍需要在代码中显式地开启和提交事务。这是因为iBATIS的批处理需要在一个事务内执行,才能确保所有操作作为一个整体执行。例如,下面的代码展示了如何在...

    iBatis批处理

    程序员的素养 程序员在工作中经常会遇到各式各样的问题和挑战,要想成为一名优秀的程序员,不仅需要具备扎实的技术能力,还需要有良好的职业素养。本文将围绕程序员的四大核心素养展开讨论,分别是:定位、主动、...

    ibatis批处理

    iBatis 批处理是一种高效的数据操作方式,尤其在处理大量数据时,可以显著提高性能。iBatis 提供了两种批处理的实现方法:在代码中直接进行循环操作和在配置文件中进行循环操作。 **1. 直接在代码中进行循环操作** ...

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

    iBatis批处理实现方式浅析 iBatis是一个功能强大的持久层框架,提供了多种方式来实现批处理操作。批处理是指将多个SQL语句组合成一个批处理单元,然后将其执行到数据库中,以提高数据库操作的效率。在iBatis中,...

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

    本文将深入探讨如何利用Ibatis实现一对多关系、批处理、事务管理和与Spring及Struts2的集成。 首先,让我们来看一下“一对多”关系。在数据库设计中,一对多关系很常见,比如一个用户可以有多个订单。在Ibatis中,...

    ibatis api,ibatis文档,ibatis说明文档

    Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责SQL映射,将数据库操作与业务逻辑解耦,使得开发者可以更专注于业务逻辑的实现,而无需关心繁琐的SQL语句编写。本篇文章将深入探讨Ibatis API、文档...

    ibatis教程,ibatis帮助文档

    1. SqlMapClient:它是iBATIS的主要接口,负责执行SQL映射和批处理操作。提供多种方法如queryForObject、queryForMap等,用于执行不同的查询或更新操作。 2. sqlmapconfig.xml:这是iBATIS的全局配置文件,包含了...

    ibatis应对批量update

    ### ibatis应对批量update 在处理大量数据更新时,传统的for循环方式往往会导致效率低下。这是因为每一次循环都需要执行一次数据库连接操作,对于批量更新来说,这样的处理方式显然不够高效。为了解决这个问题,...

    ibatis批量处理

    iBatis提供了批处理功能,可以在一次数据库连接中执行多个SQL语句,这极大地提高了处理大量数据时的性能。iBatis通过`SqlMapClient`接口提供了几个关键方法来实现批处理: 1. **`startBatch()`**:开始批处理。 2. ...

    ibatis批量存储

    本文将深入探讨“ibatis批量存储”这一主题,基于给定的文件名,我们将依次解析Ibatis中的iterate标签、批处理、foreach标签以及如何在Ibatis中使用HashMap。 1. Iterate标签详解及应用: Ibatis的iterate标签主要...

    IBatis .NET框架实例

    通过合理的缓存策略、批处理和预编译SQL等手段,IBatis可以在不影响灵活性的同时提供良好的性能。 总结,IBatis .NET为.NET开发者提供了一种直观、灵活的方式来处理数据库操作。通过学习这个实例,你可以掌握如何...

    ibatis系列 详细介绍

    8. **性能优化**:提供一些关于提高iBATIS性能的建议,如合理设计SQL、使用批处理等。 《ibatis.pdf》可能是iBATIS的官方文档或综合指南,可能包含更广泛的内容,如最佳实践、高级特性、与其他框架的集成等。 ...

    ibatis基础教学文档

    1. SqlMapClient:它是iBATIS的主要接口,负责执行SQL映射和批处理操作。提供了如queryForObject、queryForMap等方法来执行查询或更新操作。 2. sqlmapconfig.xml:这是全局配置文件,定义了数据源、事务管理器等...

    ibatis jar包.zip

    9. **性能优化**:通过预编译SQL语句、批处理等技术,iBATIS能够有效地提高数据库操作的性能。 总之,"ibatis jar包.zip" 提供了使用iBATIS框架进行数据库访问所需的全部组件,使得开发者能够快速地构建数据驱动的...

    ibatis-common.jar包

    它提供了两种基本的执行模式:SimpleExecutor(简单执行器)和BatchExecutor(批处理执行器),前者每次执行一条SQL,后者则将多条SQL语句合并成一个批处理,提高效率。 4. **ParameterMap**与**ParameterMapping**...

    ibatis-2.3.0.677

    4. **Executor**:执行器接口,负责SQL语句的真正执行,它根据不同的策略实现如简单执行、批处理执行、缓存等不同模式。 5. **ParameterHandler**:参数处理器,将Java对象的参数转换为SQL语句所需的参数值。 6. *...

    ibatis in action 电子书(pdf)

    8. **高级话题**:涵盖与iBATIS相关的高级主题,如批处理、延迟加载、自定义类型处理器、插件扩展等,提升开发者对iBATIS框架的深度理解。 9. **最佳实践**:提供实用的项目开发建议,如如何设计合理的映射文件结构...

    ibatis的3个jar包.rar

    此外,它还支持事务管理和批处理,能够很好地适应大型项目的需求。在使用Ibatis时,开发者可以根据项目的规模和需求选择不同的集成方式,如Spring框架中的Ibatis整合,实现更高级的事务管理和依赖注入。 总的来说,...

    iBATIS_DAO-2.2.0.638

    7. **批处理操作**:对于批量数据操作,iBATIS提供了批处理API,可以大大提高效率。 8. **异常处理**:iBATIS将数据库操作过程中可能出现的异常进行了封装,提供了一套统一的异常处理机制。 使用iBATIS DAO 2.2.0....

    详细介绍Ibatis的用法

    - **批处理**:对于大量数据的插入或更新操作,可以使用批处理来提高效率。 - **执行SQL语句**:通过`SqlMapClient`接口提供的方法执行SQL语句。 #### 示例代码 - **执行更新操作**:使用`update`方法执行INSERT...

Global site tag (gtag.js) - Google Analytics