ibatis实现批处理
最近做一个小项目,用到Spring+iBatis。突然遇到一个很久远,却很实在的问题:在Spring下怎么使用iBatis的批处理实现?
大概是太久没有写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 最终可能抛出的异常
通过上述修改,最终能够解决第三种实现方式中的种种不足!
Spring对iBatis提供的支持还是不够完善,即便是现在最新的Spring3.0.4。最开始,本打算用Spring3.0+iBatis3.0,结果Spring报错,说找不到“com.ibatis.xxxxx”完全是iBatis2.x的包路径!汗颜~ 还是Hibernate比较得宠!
ibatis实现批处理的更多相关文章
- ibatis的批处理
(1)spring模式:尽管spring已经配置了事务,但以下代码中还是要设置事务,不然batch不会起作用;另外这里虽然设了一下事务处理,但对全局事务并不会造成影响;注:不启用事务将建立多次连接,这 ...
- Ibatis相关
XML中的#和$的区别 http://shenzhenchufa.blog.51cto.com/730213/254561 poolMaximumActiveConnections和poolMaxim ...
- iBatis框架batch处理优化 (转)
为什么要做batch处理 这个问题我就不解释了,因为我想你们肯定能比我解释的更好!如果你真的不知道,那就到Google上去搜索一下吧☻Oracle回滚段 这个问题偶也不很明白,只是 ...
- Spring Batch 批处理框架
<Spring Batch 批处理框架>基本信息作者: 刘相 出版社:电子工业出版社ISBN:9787121252419上架时间:2015-1-24出版日期:2015 年2月开本:16开页 ...
- Ibatis学习总结6--使用 SQL Map API 编程
SQL Map API 力求简洁.它为程序员提供 4 种功能:配置一个 SQL Map,执行 SQL update操作,执行查询语句以取得一个对象,以及执行查询语句以取得一个对象的 List. 配置 ...
- 图书简介:Spring Batch批处理框架
大数据时代批处理利器,国内首度原创解析Spring Batch框架. 内容简介: <Spring Batch 批处理框架>全面.系统地介绍了批处理框架Spring Batch,通过详尽的实 ...
- ibatis框架的sqlmapclient接口
SqlMapClient,是iBatis中的重要接口,这个接口涉及到对SQL映射的执行和批处理. 现在,就先了解它的对query开头方法的定义. 首先是 queryForList 方法: //指定SQ ...
- iBatis系列一
XML iBatis可以使用xml来作为参数输入以及结果返回:这个功能的优势在于某些特定的场景:还有可以通过DOM方式来作为参数传递:但是这个方式应用的比较少,如果服务器是xml服务器可以采用这种方式 ...
- 使用 getNextException() 来检索已经过批处理的特定元素的异常。 ERRORCODE=-4228, SQLSTATE=null
今天查询了一天发现的问题,用ibatis做批量操作时,报错: [非原子批处理出现故障]使用 getNextException() 来检索已经过批处理的特定元素的异常. ERRORCODE=-4228, ...
随机推荐
- s21day25 python笔记
s21day25 python笔记 正则表达式 1.定义 定义:正则表达式是一种规则匹配字符串的规则 re模块本身只是用来操作正则表达式的,和正则本身没关系 为什么要有正则表达式? 匹配字符串 一个人 ...
- ffmpeg学习(一)——在window7下编译ffmpeg
FFmpeg是一个开源免费跨平台的视频和音频流项目,它提供了录制.转换以及流化音视频的完整解决方案.本文作者将尝试使用该库实现一个可适应复杂网络环境的, 支持标准rtsp协议的流媒体服务器.由于Vis ...
- solr-DIH:dataimport增量全量创建索引
索引创建完毕,就要考虑怎么定时的去重建, 除了写solrj,可以定时调用下面两条url进行增量或者全量创建索引 全量:http://ip:port/webapp_name/core_name/da ...
- PyQt4 QListWidget 使用教程
转自:http://blog.csdn.net/seeground/article/details/49177387?locationNum=3&fps=1 listWidget = QLis ...
- [uwp]ImageSource和byte[]相互转换
最近做一个小app遇到一个问题,到目前还没有比较好的解决方法(可能是我查的资料不够多) 需求如下: 1.把一个Image中的图像保存到字节数组: 2.把字节数组转换为ImageSource,通过Ima ...
- C# 收银机顾显(客显)及打印小票(58热敏打印机)
最近做winform收银机,设计顾显及打印小票总结. 1.顾显(串口COM1) 只涉及到总计,所以只是简单的功能. public static ClientDisplayResult Display( ...
- poj做的题
1699 1080 1170 1239(不错) 1659(读读怎么写)
- 【12c OCP】CUUG OCP认证071考试原题解析(36)
36.choose the best answer View the Exhibits and examine the structures of the PRODUCTS, SALES, and C ...
- Code Chef February Challenge 2019题解
传送门 \(HMAPPY2\) 咕 话说这题居然卡\(scanf\)的么??? int T;cin>>T; while(T--){ cin>>n>>a>> ...
- aspx代码审计-1
今天和大家分享一下aspx网站的代码审计,漏洞类型就是SQL注入和cookie欺骗. 本文作者:i春秋签约作家——非主流 今天看的cms名字叫做:XX星员工请假系统 我们首先看一下网站的目录结构: 其 ...