iBatis批处理实现(Spring环境)

来源:互联网 发布:对大数据的理解和认识 编辑:程序博客网 时间:2024/05/17 22:41

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

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

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

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

Java代码 
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操作为例,把它们结合到一起: 
Java代码 
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实现 
Java代码 
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框架时通常都采用了回调模式,从而避免了事务代码入侵的可能! 
修改后的代码如下: 
Java代码 
@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标识!即,待遍历对象不能修改! 
引用public void create(final List<Reply> replyList)
这样做,就将事务处理的控制权完全交给了Spring! 
简述: 
SqlMapClientCallback 回调接口doInSqlMapClient(SqlMapExecutor executor) 回调实现方法DataAccessException 最终可能抛出的异常
通过上述修改,最终能够解决第三种实现方式中的种种不足! 

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