讀mybatis源碼之十四:mybatis事務處理

1、自身事務處理

public void doxxxxx(){
 TransactionFactory transactionFactory = new JdbcTransactionFactory();
 userMapper userDao=getSession().getMapper(UserMapper.class);
 Transaction newTransaction=transactionFactory.newTransaction(getSession().getConnection());
 try {
  userDao.insert(xxx);
  userDao.update(xxx);
 } catch (Exception e) {
  newTransaction.rollback();
  e.printStackTrace();
 } finally {
    newTransaction.close();
 }
}
可以看出主要是事務連接。

2、與spring集成後,事務處理

BlogMapper mapper = (BlogMapper)app.getBean("blogMapper");
    Blog sblog = new Blog();
    sblog.setId(2);
    sblog.setName("測試加密555");
    sblog.setAddr("測試加密--------------123444");
    mapper.insertBlogByObj(sblog);
這種數據能夠提交上去,爲什麼呢? 看看與spring集成後它的處理方式
首先看如何得到mapper的,通過MapperFactoryBean的getObject()    方法得到
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }
那getSqlSession()又是如何得到的呢?跟蹤是通過SqlSessionTemplate得到,SqlSessionTemplate裏面是什麼呢?
發現是一個sqlSessionProxy代理:
 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {
    notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
    notNull(executorType, "Property 'executorType' is required");
    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());
  }
具體看SqlSessionInterceptor,就可以看出爲什麼spring集成後,不顯示提交,也能自動提交了:
  private class SqlSessionInterceptor implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      final SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
      }
    }
  }

  if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
這部分重點,如果配置了事務,就由配置事務處理,沒有配置就直接提交,所以這裏相當於他幫你提交了。
closeSqlSession裏面也是一樣,如果有事務,是session釋放,如果沒有就是session關閉,跟蹤下去就是事務關閉,mybatis  spring結合后里面SpringManagedTransaction的close,用的DataSourceUtils的releaseConnection
  public void close() throws SQLException {
    releaseConnection(this.connection, this.dataSource);
  }






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章