探索的ibatis DAO事務(wù)管理模塊
ibatis DAO 框架提供了事務(wù)管理模塊。而這個(gè)事務(wù)管理可以應(yīng)用到很多場(chǎng)合,包括JDBC、Hibernate、JTA、SQLMAP等。
下面以最簡(jiǎn)單的JDBC來(lái)分析一下ibatis DAO如何實(shí)現(xiàn)事務(wù)管理。
首先來(lái)看一段代碼:
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(); //第一個(gè)事務(wù)
daoManager.startTransaction(); //開(kāi)始第二個(gè)事務(wù)
orderDao.method1();
orderDao.method2();
daoManager.commitTransaction();//提交第二個(gè)事務(wù)
} finally {
daoManager.endTransaction();
}
}
}
在method()方法里有著兩個(gè)事務(wù),如果在方法里不顯式的調(diào)用daoManager.startTransaction(),則每個(gè)ibatis DAO的一次方法調(diào)用就是一個(gè)獨(dú)立的事務(wù)。
ibatis DAO事務(wù),有兩個(gè)核心接口DaoTransactionManager和DaoTransaction
對(duì)應(yīng)著不同的數(shù)據(jù)庫(kù)持久層實(shí)現(xiàn),兩個(gè)接口分別對(duì)應(yīng)著不同實(shí)現(xiàn);
查看ibatis 代碼,可以發(fā)現(xiàn)這些manager實(shí)現(xiàn)事務(wù),就是調(diào)用事務(wù)源的事務(wù)管理方法。
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以什么依據(jù)進(jìn)行事務(wù)管理呢?DaoTransactionState看看DaoTransactionState的代碼,非常簡(jiǎn)單,四個(gè)常量來(lái)表示事務(wù)處于的不同的狀態(tài)。
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();
那么實(shí)際程序中是如何進(jìn)行事務(wù)管理的呢?在第一段代碼中,我們是這樣取得DAO
orderDao = (OrderDao) daoManager.getDao(OrderDao.class);
實(shí)際daoManager返回的并不是orderDao的具體實(shí)現(xiàn)類,它返回的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;
}
看到這段代碼就非常清楚了,每調(diào)用ibatis DAO的一次方法時(shí),如果不顯式的調(diào)用daoManager.startTransaction(),就會(huì)成為單獨(dú)的一個(gè)事務(wù)。再看看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控制多個(gè)DAO的事務(wù)實(shí)際是讓這些DAO共用了一個(gè)DaoTransaction(ThreadLocal),一個(gè)Connection
這里是一個(gè)事務(wù)源的情況,如果多個(gè)事務(wù)源之間要完成全局事務(wù),還是老老實(shí)實(shí)用分布式事務(wù)管理服務(wù)吧。
【編輯推薦】
- ibatis官方提示文檔中的錯(cuò)誤
- ibtis配置之添加ibatis Dao支持
- 分析ibatis dao框架
- ibatis DAO入門進(jìn)階寶典
- 了解iBatis.Net中的ResultMap
【責(zé)任編輯:桑丘 TEL:(010)68476606】