从4个层面分析这部分实现: iBatis的基本实现 基于事务的iBatis的基本实现 基于事务的Spring+iBatis实现 基于回调方式的Spring+iBatis实现 1.iBatis的基本实现 iBatis通过SqlMapClient提供了一组方法用于批处理实现: 这是基于iBatis的最基本实现,如果你一步一步debug,你会发现:其实,数据库已经执行了插入操作! 因此,除了这两个核心方法外,你还需要开启事务支持。否则,上述代码只不过是个空架子! 2.基于事务的iBatis的基本实现 事务处理: replyList是一个List,要把这个List插入到数据库,就需要经过这三个步骤: 注意使用同一个sqlMapClient: SqlMapClient sqlMapClient = sqlMapClientTemplate.getSqlMapClient(); 如果直接sqlMapClientTemplate执行insert()方法,将会造成异常! 想想,还有什么问题?其实问题很明显,虽然解决了批处理实现的问题,却造成了事务代码入侵的新问题。
这么做,有点恶心! 除此之外,异常的处理也很恶心,不能够简单的包装为 DataAccessException 就无法被Spring当作统一的数据库操作异常做处理。 4.基于回调方式的Spring+iBatis实现 如果观察过Spring的源代码,你一定知道,Spring为了保持事务统一控制,在实现ORM框架时通常都采用了回调模式,从而避免了事务代码入侵的可能!
修改后的代码如下: 注意,待遍历的参数replyList需要加入final标识!即,待遍历对象不能修改!
简述:
- startBatch() 开始批处理
- executeBatch() 执行批处理
Java代码
![收藏代码](http://static.oschina.net/uploads/img/201304/27181145_LjIh.png)
- 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();
- }
- }
- startTransaction() 开始事务
- commitTransaction() 提交事务
- endTransaction() 结束事务
Java代码
![收藏代码](http://static.oschina.net/uploads/img/201304/27181145_LjIh.png)
- 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();
- }
- }
- }
- 开始批处理 startBatch()
- 插入 insert()
- 执行批处理 executeBatch()
Java代码
![收藏代码](http://static.oschina.net/uploads/img/201304/27181145_LjIh.png)
- 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();
- }
- }
- }
- }
![](http://static.oschina.net/uploads/img/201304/27181145_YeBn.gif)
![](http://static.oschina.net/uploads/img/201304/27181145_tSt9.gif)
Java代码
![收藏代码](http://static.oschina.net/uploads/img/201304/27181145_LjIh.png)
- @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;
- }
- });
- }
引用
public void create(final List<Reply> replyList)
这样做,就将事务处理的控制权完全交给了Spring! ![](http://static.oschina.net/uploads/img/201304/27181145_tSt9.gif)
- SqlMapClientCallback 回调接口
- doInSqlMapClient(SqlMapExecutor executor) 回调实现方法
- DataAccessException 最终可能抛出的异常