最近做一个小项目,用到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. try {
  3. // 开始批处理
  4. sqlMapClient.startBatch();
  5. for (Reply reply: replyList) {
  6. // 插入操作
  7. sqlMapClient.insert("Reply.create", reply);
  8. }
  9. // 执行批处理
  10. sqlMapClient.executeBatch();
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. }
  14. }

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

2.基于事务的iBatis的基本实现 
事务处理: 

  1. startTransaction() 开始事务
  2. commitTransaction() 提交事务
  3. endTransaction() 结束事务

我们以insert操作为例,把它们结合到一起: 

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

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. try {
  6. // 开始事务
  7. sqlMapClient.startTransaction();
  8. // 开始批处理
  9. sqlMapClient.startBatch();
  10. for (Reply reply : replyList) {
  11. // 插入操作
  12. sqlMapClient.insert("Reply.create", reply);
  13. }
  14. // 执行批处理
  15. sqlMapClient.executeBatch();
  16. // 提交事务 交给Spring统一控制
  17. // sqlMapClient.commitTransaction();
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. } finally {
  21. try {
  22. // 结束事务
  23. sqlMapClient.endTransaction();
  24. } catch (SQLException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }
  29. }

注意使用同一个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. executor.executeBatch();
  16. return null;
  17. }
  18. });
  19. }

注意,待遍历的参数replyList需要加入final标识!即,待遍历对象不能修改! 

引用
public void create(final List<Reply> replyList)

这样做,就将事务处理的控制权完全交给了Spring! 
简述: 

  1. SqlMapClientCallback 回调接口
  2. doInSqlMapClient(SqlMapExecutor executor) 回调实现方法
  3. DataAccessException 最终可能抛出的异常

通过上述修改,最终能够解决第三种实现方式中的种种不足!

Spring对iBatis提供的支持还是不够完善,即便是现在最新的Spring3.0.4。最开始,本打算用Spring3.0+iBatis3.0,结果Spring报错,说找不到“com.ibatis.xxxxx”完全是iBatis2.x的包路径!汗颜~ 还是Hibernate比较得宠!

ibatis实现批处理的更多相关文章

  1. ibatis的批处理

    (1)spring模式:尽管spring已经配置了事务,但以下代码中还是要设置事务,不然batch不会起作用;另外这里虽然设了一下事务处理,但对全局事务并不会造成影响;注:不启用事务将建立多次连接,这 ...

  2. Ibatis相关

    XML中的#和$的区别 http://shenzhenchufa.blog.51cto.com/730213/254561 poolMaximumActiveConnections和poolMaxim ...

  3. iBatis框架batch处理优化 (转)

    为什么要做batch处理        这个问题我就不解释了,因为我想你们肯定能比我解释的更好!如果你真的不知道,那就到Google上去搜索一下吧☻Oracle回滚段    这个问题偶也不很明白,只是 ...

  4. Spring Batch 批处理框架

    <Spring Batch 批处理框架>基本信息作者: 刘相 出版社:电子工业出版社ISBN:9787121252419上架时间:2015-1-24出版日期:2015 年2月开本:16开页 ...

  5. Ibatis学习总结6--使用 SQL Map API 编程

    SQL Map API 力求简洁.它为程序员提供 4 种功能:配置一个 SQL Map,执行 SQL update操作,执行查询语句以取得一个对象,以及执行查询语句以取得一个对象的 List. 配置  ...

  6. 图书简介:Spring Batch批处理框架

    大数据时代批处理利器,国内首度原创解析Spring Batch框架. 内容简介: <Spring Batch 批处理框架>全面.系统地介绍了批处理框架Spring Batch,通过详尽的实 ...

  7. ibatis框架的sqlmapclient接口

    SqlMapClient,是iBatis中的重要接口,这个接口涉及到对SQL映射的执行和批处理. 现在,就先了解它的对query开头方法的定义. 首先是 queryForList 方法: //指定SQ ...

  8. iBatis系列一

    XML iBatis可以使用xml来作为参数输入以及结果返回:这个功能的优势在于某些特定的场景:还有可以通过DOM方式来作为参数传递:但是这个方式应用的比较少,如果服务器是xml服务器可以采用这种方式 ...

  9. 使用 getNextException() 来检索已经过批处理的特定元素的异常。 ERRORCODE=-4228, SQLSTATE=null

    今天查询了一天发现的问题,用ibatis做批量操作时,报错: [非原子批处理出现故障]使用 getNextException() 来检索已经过批处理的特定元素的异常. ERRORCODE=-4228, ...

随机推荐

  1. s21day25 python笔记

    s21day25 python笔记 正则表达式 1.定义 定义:正则表达式是一种规则匹配字符串的规则 re模块本身只是用来操作正则表达式的,和正则本身没关系 为什么要有正则表达式? 匹配字符串 一个人 ...

  2. ffmpeg学习(一)——在window7下编译ffmpeg

    FFmpeg是一个开源免费跨平台的视频和音频流项目,它提供了录制.转换以及流化音视频的完整解决方案.本文作者将尝试使用该库实现一个可适应复杂网络环境的, 支持标准rtsp协议的流媒体服务器.由于Vis ...

  3. solr-DIH:dataimport增量全量创建索引

    索引创建完毕,就要考虑怎么定时的去重建, 除了写solrj,可以定时调用下面两条url进行增量或者全量创建索引   全量:http://ip:port/webapp_name/core_name/da ...

  4. PyQt4 QListWidget 使用教程

    转自:http://blog.csdn.net/seeground/article/details/49177387?locationNum=3&fps=1 listWidget = QLis ...

  5. [uwp]ImageSource和byte[]相互转换

    最近做一个小app遇到一个问题,到目前还没有比较好的解决方法(可能是我查的资料不够多) 需求如下: 1.把一个Image中的图像保存到字节数组: 2.把字节数组转换为ImageSource,通过Ima ...

  6. C# 收银机顾显(客显)及打印小票(58热敏打印机)

    最近做winform收银机,设计顾显及打印小票总结. 1.顾显(串口COM1) 只涉及到总计,所以只是简单的功能. public static ClientDisplayResult Display( ...

  7. poj做的题

    1699 1080 1170 1239(不错) 1659(读读怎么写)

  8. 【12c OCP】CUUG OCP认证071考试原题解析(36)

    36.choose the best answer View the Exhibits and examine the structures of the PRODUCTS, SALES, and C ...

  9. Code Chef February Challenge 2019题解

    传送门 \(HMAPPY2\) 咕 话说这题居然卡\(scanf\)的么??? int T;cin>>T; while(T--){ cin>>n>>a>> ...

  10. aspx代码审计-1

    今天和大家分享一下aspx网站的代码审计,漏洞类型就是SQL注入和cookie欺骗. 本文作者:i春秋签约作家——非主流 今天看的cms名字叫做:XX星员工请假系统 我们首先看一下网站的目录结构: 其 ...