项目开发-iBatis事宜源码之开启新事务

项目开发-iBatis事务源码之开启新事务

      iBatis事务源码流程整理如下。主要包括事务的使用以及各个方法的调用过程。

   iBatis的事务使用

     iBatis只有对单个的增、删、改操作添加了默认事务处理过程,如果客户端没有开启事务,那么就为这些操作自动添加事务,以保证这些修改操作会被提交。因此,客户端多条语句的原子操作,需要自己调用iBatis的事务方法,将这些操作封装在事务中来实现。典型的事务使用代码如下:

 * try {
 *   <b>sqlMap.startTransaction()</b>
 *   Employee emp2 = new Employee();
 *   // ...set emp2 data
 *   Integer generatedKey = (Integer) <b>sqlMap.insert ("insertEmployee", emp2)</b>;
 *   emp2.setFavouriteColour ("green");
 *   <b>sqlMap.update("updateEmployee", emp2)</b>;
 *   <b>sqlMap.commitTransaction()</b>;
 * } finally {
 *   <b>sqlMap.endTransaction()</b>;
 * }
   这是SqlMapClient类的注释部分,该类的注释本质上就是iBatis的SqlMapClient的API文档。例如:开户流程中需要保证账户和人员信息的原子性。示例如下
SqlMapClient client = SimpleExample.getInstance();
try {
	client.startTransaction();
	SimpleExample.insertPerson(p);
	SimpleExample.insertAccount(account);
	client.commitTransaction();
} catch (SQLException execption) {
}finally{
	try {
		client.endTransaction();
	} catch (SQLException e) {
		e.printStackTrace();
	}
}

  startTransaction

   1)SqlMapClientImpl提供的startTransaction()方法
  public void startTransaction() throws SQLException {
    getLocalSqlMapSession().startTransaction();
  }
  protected SqlMapSessionImpl getLocalSqlMapSession() {
    SqlMapSessionImpl sqlMapSession = (SqlMapSessionImpl) localSqlMapSession.get();
    if (sqlMapSession == null || sqlMapSession.isClosed()) {
      sqlMapSession = new SqlMapSessionImpl(this);
      localSqlMapSession.set(sqlMapSession);
    }
    return sqlMapSession;
  }
   2)SqlMapSessionImpl类的startTransaction()
  public SqlMapSessionImpl(SqlMapClientImpl client) {
    this.delegate = client.getDelegate();
    this.sessionScope = this.delegate.beginSessionScope();
    this.sessionScope.setSqlMapClient(client);
    this.sessionScope.setSqlMapExecutor(client);
    this.sessionScope.setSqlMapTxMgr(client);
    this.closed = false;
  }
  public void startTransaction() throws SQLException {
    delegate.startTransaction(sessionScope);
  }
   3)SqlMapExecutorDelegate的startTransaction()
  public void startTransaction(SessionScope sessionScope) throws SQLException {
    try {
      txManager.begin(sessionScope);
    } catch (TransactionException e) {
      throw new NestedSQLException("Could not start transaction.  Cause: " + e, e);
    }
  }
   4)TransactionManager的begin()方法
  public void begin(SessionScope sessionScope, int transactionIsolation) throws SQLException, TransactionException {
    Transaction trans = sessionScope.getTransaction();
    TransactionState state = sessionScope.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.");
    }

    trans = config.newTransaction(transactionIsolation);
    sessionScope.setCommitRequired(false);

    sessionScope.setTransaction(trans);
    sessionScope.setTransactionState(TransactionState.STATE_STARTED);
  }
   5)TransactionConfig的newTransaction()代码
  public Transaction newTransaction(int transactionIsolation) throws SQLException, TransactionException {
    return new JdbcTransaction(dataSource, transactionIsolation);
  }
     该操作执行完成后,SqlMapSessionImpl的属性SessionScope中存储了当前会话的事务的信息:当前新建的事务对象,以及事务的状态(新建状态)和提交标识(false)。