iBATIS DAO事務(wù)淺析
iBATIS DAO事務(wù)的理解要從iBATIS DAO 框架開始,它提供了事務(wù)管理模塊。而這個(gè)事務(wù)管理可以應(yīng)用到很多場合,包括JDBC、Hibernate、JTA、SQLMAP等。
下面以最簡單的JDBC來分析一下其如何實(shí)現(xiàn)iBATIS DAO事務(wù)管理。
首先來看一段代碼:
- 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(); //開始第二個(gè)事務(wù)
- orderDao.method1();
- orderDao.method2();
- daoManager.commitTransaction();//提交第二個(gè)事務(wù)
- } finally {
- daoManager.endTransaction();
- }
- }
- }
在method()方法里有著兩個(gè)事務(wù),如果在方法里不顯式的調(diào)用daoManager.startTransaction(),則每個(gè)DAO的一次方法調(diào)用就是一個(gè)獨(dú)立的事務(wù)。
iBATIS DAO事務(wù),有兩個(gè)核心接口DaoTransactionManager和DaoTransaction
對應(yīng)著不同的數(shù)據(jù)庫持久層實(shí)現(xiàn),兩個(gè)接口分別對應(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ù)處理事務(wù)呢?DaoTransactionState看看DaoTransactionState的代碼,非常簡單,四個(gè)常量來表示事務(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í)際程序中是如何控制事務(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)用DAO的一次方法時(shí),如果不顯式的調(diào)用daoManager.startTransaction(),就會(huì)成為單獨(dú)的一個(gè)iBATIS DAO事務(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ù)吧(jta)。
iBATIS DAO事務(wù)的相關(guān)信息就向你介紹到這里,之后的文章里我們還會(huì)提及的,請關(guān)注。
【編輯推薦】