在Ibatis中我们要执行一个事务,代码是这样的:
?
sqlMapClient.startTransaction (); sqlMapClient.add (xxxxx); sqlMapClient.update (xxxxx); sqlMapClient.commitTransaction ();看到这段代码你会不会有一个问题,sqlMapClient里面到底是怎么做的?
日期:2014-05-16 浏览次数:20408 次
在Ibatis中我们要执行一个事务,代码是这样的:
?
sqlMapClient.startTransaction (); sqlMapClient.add (xxxxx); sqlMapClient.update (xxxxx); sqlMapClient.commitTransaction ();看到这段代码你会不会有一个问题,sqlMapClient里面到底是怎么做的?
?
1. 调用sqlMapClient.startTransaction时会通知数据库事务开始了,然后依次执行add和update,最后告诉数据库提交事务。
2.调用sqlMapClient.startTransaction时并没有通知数据库,只不过在sqlMapClient这个对象中记录了一个标志,然后下面的add操作与update操作也没有实际上执行语句,只是产生了sql语句并存储在sqlMapClient中。最终调用sqlMapClient.commitTransaction时,会把产生的这些sql语句作为一个事务一次提交执行。
?
google了一下,没发现有人提出这样的问题。只好自己看源码。下面是源码的调用关系。
SqlMapClientImpl.startTransaction() --->
?
public void startTransaction(int transactionIsolation) throws SQLException { getLocalSqlMapSession().startTransaction(transactionIsolation); }这里的?getLocalSqlMapSession()返回了一个SqlMapSession对象,这个对象非常重要,它管理了一次事务的状态,为什么重要后面会讲到。
?
继续跟踪调用
------>SqlMapSessionImpl.startTransaction(transactionIsolation)
------>SqlMapExecutorDelegate.startTransaction(session, transactionIsolation)
------>TransactionManager.begin(session, transactionIsolation)这个方法是重点,看代码:
?
public void begin(SessionScope session, int transactionIsolation) throws SQLException, TransactionException { Transaction trans = session.getTransaction(); TransactionState state = session.getTransactionState(); if (state == TransactionState.STATE_STARTED) { throw new TransactionException("TransactionManager could not start a new transaction. " + "A transaction is already started."); } else if (state == TransactionState.STATE_USER_PROVIDED) { throw new TransactionException("TransactionManager could not start a new transaction. " + "A user provided connection is currently being used by this session. " + "The calling .setUserConnection (null) will clear the user provided transaction."); } txThrottle.increment(); try { trans = transactionConfig.newTransaction(transactionIsolation); ------------------------------- session.setCommitRequired(false); } catch (SQLException e) { txThrottle.decrement(); throw e; } catch (TransactionException e) { txThrottle.decrement(); throw e; } session.setTransaction(trans); ---------------------------------------------- session.setTransactionState(TransactionState.STATE_STARTED); }?
?
注意用横线标出的那两句,首先创建了一个Transcaction,然后把它放入了session,为什么放入session,很重要,继续往下看。?
transactionConfig.newTransaction(transactionIsolation);中创建了一个JdbcTransaction
看看JdbcTransaction的代码:
?
public class JdbcTransaction implements Transaction { private static final Log connectionLog = LogFactory.getLog(Connection.class); private DataSource dataSource; private Connection connection; private IsolationLevel isolationLevel = new IsolationLevel(); public JdbcTransaction(DataSource ds, int isolationLevel) throws TransactionException { // Check Parameters dataSource = ds; if (dataSource == null) { throw new TransactionException("JdbcTransaction initialization failed. DataSource was null."); } this.isolationLevel.setIsolationLevel(isolationLevel); } private void init() throws SQLException, TransactionException { // Open JDBC