posts - 193,  comments - 520,  trackbacks - 0
ibatis DAO 框架提供了事务管理模块。而这个事务管理可以应用到很多场合,包括JDBC、Hibernate、JTA、SQLMAP等。
下面以最简单的JDBC来分析一下其如何实现事务管理。
首先来看一段代码:
public class OrderService {

  
private DaoManager daoManager;

  
private OrderDao orderDao;

  
public OrderService() {
    daoManager 
= DaoConfig.getDaoManager();
    orderDao 
= (OrderDao) daoManager.getDao(OrderDao.class);
  }


  
public void method() {
    
try {
      
//  a separate transaction
      orderDao.method1();   //第一个事务

      daoManager.startTransaction(); 
//开始第二个事务

      orderDao.method1();
      orderDao.method2();

      daoManager.commitTransaction();
//提交第二个事务
    }
 finally {
      daoManager.endTransaction();
    }

  }

  }
  在method()方法里有着两个事务,如果在方法里不显式的调用daoManager.startTransaction(),则每个DAO的一次方法调用就是一个独立的事务。
  ibatis DAO事务,有两个核心接口DaoTransactionManager和DaoTransaction
  对应着不同的数据库持久层实现,两个接口分别对应着不同实现
  查看ibatis 代码,可以发现这些manager实现事务,就是调用事务源的事务操作方法

  JdbcDaoTransactionManager
  public void commitTransaction(DaoTransaction trans) {
    ((JdbcDaoTransaction) trans).commit();
  }

 JdbcDaoTransaction
  public JdbcDaoTransaction(DataSource dataSource) {
    
try {
      connection 
= dataSource.getConnection();
      
if (connection == null{
        
throw new DaoException("Could not start transaction.  Cause: The DataSource returned a null connection.");
      }

      
if (connection.getAutoCommit()) {
        connection.setAutoCommit(
false);
      }

      
if (connectionLog.isDebugEnabled()) {
        connection 
= ConnectionLogProxy.newInstance(connection);
      }

    }
 catch (SQLException e) {
      
throw new DaoException("Error starting JDBC transaction.  Cause: " + e);
    }

  }

  
  
public void commit() {
    
try {
      
try {
        connection.commit();
      }
 finally {
        connection.close();
      }

    }
 catch (SQLException e) {
      
throw new DaoException("Error committing JDBC transaction.  Cause: " + e);
    }

  }

  那么DaoTransactionManager以什么依据处理事务呢?DaoTransactionState看看DaoTransactionState的代码,非常简单,四个常量来表示事务处于的不同的状态
  public static final DaoTransactionState ACTIVE = new DaoTransactionState();
  
public static final DaoTransactionState INACTIVE = new DaoTransactionState();
  
public static final DaoTransactionState COMMITTED = new DaoTransactionState();
  
public static final DaoTransactionState ROLLEDBACK = new DaoTransactionState(); 
  那么实际程序中是如何控制事务的呢
  在第一段代码中,我们是这样取得DAO
  orderDao = (OrderDao) daoManager.getDao(OrderDao.class);
  实际daoManager返回的并不是orderDao的具体实现类,它返回的DaoProxy

DaoProxy
  public Object invoke(Object proxy, Method method, Object[] args)
      
throws Throwable {
    Object result 
= null;
    
if (PASSTHROUGH_METHODS.contains(method.getName())) {
      
try {
        result 
= method.invoke(daoImpl.getDaoInstance(), args);
      }
 catch (Throwable t) {
        
throw ClassInfo.unwrapThrowable(t);
      }

    }
 else {
      StandardDaoManager daoManager 
= daoImpl.getDaoManager();
      DaoContext context 
= daoImpl.getDaoContext();

      
if (daoManager.isExplicitTransaction()) {
        
// Just start the transaction (explicit)
        try {
          context.startTransaction();
          result 
= method.invoke(daoImpl.getDaoInstance(), args);
        }
 catch (Throwable t) {
          
throw ClassInfo.unwrapThrowable(t);
        }

      }
 else {
        
// Start, commit and end the transaction (autocommit)
        try {
          context.startTransaction();
          result 
= method.invoke(daoImpl.getDaoInstance(), args);
          context.commitTransaction();
        }
 catch (Throwable t) {
          
throw ClassInfo.unwrapThrowable(t);
        }
 finally {
          context.endTransaction();
        }

      }


    }

    
return result;
  }
  看到这段代码就非常清楚了,每调用DAO的一次方法时,如果不显式的调用daoManager.startTransaction(),就会成为单独的一个事务。再看看ibatis为我们提供的摸板JdbcDaoTemplate
  protected Connection getConnection() {
    DaoTransaction trans 
= daoManager.getTransaction(this);
    
if (!(trans instanceof ConnectionDaoTransaction)) {
      
throw new DaoException("The DAO manager of type " + daoManager.getClass().getName() +
          
" cannot supply a JDBC Connection for this template, and is therefore not" +
          
"supported by JdbcDaoTemplate.");
    }

    
return ((ConnectionDaoTransaction) trans).getConnection();
  }

  ibatis控制多个DAO的事务实际是让这些DAO共用了一个DaoTransaction(ThreadLocal),一个Connection
 
  这里是一个事务源的情况,如果多个事务源之间要完成全局事务,还是老老实实用分布式事务管理服务吧(jta)

http://www.blogjava.net/ronghao 荣浩原创,转载请注明出处:)
posted on 2006-01-20 17:50 ronghao 阅读(7200) 评论(6)  编辑  收藏 所属分类: 工作日志

FeedBack:
# re: ibatis DAO 事务探索
2006-12-06 03:14 | ..
无聊  回复  更多评论
  
# re: ibatis DAO 事务探索
2007-02-10 11:58 | yidinghe
很棒!很有启发性!谢谢!  回复  更多评论
  
# re: ibatis DAO 事务探索
2007-07-25 23:43 | zph
不错,谢谢  回复  更多评论
  
# re: ibatis DAO 事务探索
2008-03-26 10:37 | 屹砾
先看一下,我也遇到了这个问题,一个事务操纵多个行为,不过事务总是没有原子性,比较严重。  回复  更多评论
  
# re: ibatis DAO 事務探索
2009-10-23 13:19 | w
@..
人家辛苦發表- -說無聊真欠揍  回复  更多评论
  
# re: ibatis DAO 事务探索
2011-03-16 02:35 | leekiang
这里的好几个类在2.3版本里好像都去掉了  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2011年3月>
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789

关注工作流和企业业务流程改进。现就职于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

常用链接

留言簿(38)

随笔分类

随笔档案

文章分类

文章档案

常去的网站

搜索

  •  

最新评论

阅读排行榜

评论排行榜