|
|
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)
|
|
|
|