事务

首先需要注意的是,MyBatis的事务与HttpSession是无关的。MyBatis是基于动态代理进行Wrapper的,而HttpSession是基于Filter的。

原理

在Spring-session包中

org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke

通过MyBatis的Mapper中的动态代理前后包装实现事务,而非使用了Spring的AOP

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) {
    // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
    closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
    sqlSession = null;
    Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
    if (translated != null) {
      unwrapped = translated;
    }
  }
  throw unwrapped;
} finally {
  if (sqlSession != null) {
    closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
  }
}