mybatis源码分析(8)-----事务(mybatis管理、spring管理)

写在前面

  接口:MyBatis的事务Transaction的接口有一下实现类

    JdbcTransaction 由jdbc管理的事务(即利用Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等)

    ManagedTransaction 由容器管理事务 (这种机制MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理)

      SpringManagedTransaction(位于mybatis-spring包中) 由spring来管理事务 myBatis单独为spring的事务集成,设计的类。本文章也是重要讲解此类的原理。

  设计:工厂模式

   Transaction---TransactionTransactionFactory

    JdbcTransaction ---JdbcTransactionFactory

    ManagedTransaction ---ManagedTransactionFactory

      SpringManagedTransaction---SpringManagedTransactionFactory

   持有者:

    Executor(执行器)即对于事务的所有操作,都是由执行器来调度

      Transaction

   Transaction接口

public interface Transaction {
  //获取链接    
  Connection getConnection() throws SQLException;
  //提交
  void commit() throws SQLException;
  //回滚
  void rollback() throws SQLException;
  //关闭
  void close() throws SQLException;
}

  TransactionFactory接口

public interface TransactionFactory {
  //相关属性设置
  void setProperties(Properties props);
  //通过链接开启获取一个事务对象
  Transaction newTransaction(Connection conn);
  //通过datasource获取一个事务对象
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}

 

 

spring事务相关

   TransactionSynchronizationManager: spring 管理事务线程的抽象类,所有属性都是threadlocal和当前线程相关

public abstract class TransactionSynchronizationManager {
  
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<Map<Object, Object>>("Transactional resources"); private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations"); private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<String>("Current transaction name"); private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<Boolean>("Current transaction read-only status"); private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<Integer>("Current transaction isolation level"); private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal<Boolean>("Actual transaction active");
}

  

  当 spring开启事务管理(声明式事务、注解式事务):会初始化一个synchronizations,初始化一个空的Set<TransactionSynchronization>集合存放在当前线程中。

    public static void initSynchronization() throws IllegalStateException {
        if (isSynchronizationActive()) {
            throw new IllegalStateException("Cannot activate transaction synchronization - already active");
        }
        logger.trace("Initializing transaction synchronization");
        synchronizations.set(new LinkedHashSet<TransactionSynchronization>());
    }

   

  spring判断synchronizations是否存在,暴露的API

    public static boolean isSynchronizationActive() {
        return (synchronizations.get() != null);
    }

 

myBatis单独管理

   前提假设myBatis 和spring集成,且满足spring没有开启事务管理(声明式事务、注解式事务)

   在获取sqlSession的时候,会判断TransactionSynchronizationManager中的synchronizations是否存在:

    如果不存在,则不会注册SqlSessionHolder到resources中,也不会将SqlSessionSynchronization(myBatis对于TransactionSynchronization接口的实现类)注册到synchronizations中。

  private static void registerSessionHolder(SqlSessionFactory sessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator, SqlSession session) {
    SqlSessionHolder holder;
//判断spring是否管理事务,即synchronizations是否存在值
if (TransactionSynchronizationManager.isSynchronizationActive()) { Environment environment = sessionFactory.getConfiguration().getEnvironment(); if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registering transaction synchronization for SqlSession [" + session + "]"); } holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
//将SqlSessionFactory和SqlSessionHolder 绑定,注册到TransactionSynchronizationManager.resources中 TransactionSynchronizationManager.bindResource(sessionFactory, holder);
//注册sqlSessionSynchronization到TransactionSynchronizationManager.synchronizations中 TransactionSynchronizationManager.registerSynchronization(
new SqlSessionSynchronization(holder, sessionFactory)); holder.setSynchronizedWithTransaction(true); holder.requested(); } else { if (TransactionSynchronizationManager.getResource(environment.getDataSource()) == null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional"); } } else { throw new TransientDataAccessResourceException( "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"); } } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active"); } }

 

  sqlSession调用Executor-->statmentHandler 执行sql的流程后,判断是否commit,已经sqlSession是否关闭。

  private class SqlSessionInterceptor implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
//sqlSession目标方法执行 Object result
= method.invoke(sqlSession, args);
//判断resources中是否存在绑定的sqlSession、sqlSessionFactory。不存在直接提交commit
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) {
//改方法中会判断resources中是否存在绑定的sqlSession、sqlSessionFacotory。如果不存在,关闭sqlSession closeSqlSession(sqlSession, SqlSessionTemplate.
this.sqlSessionFactory); } } } }
  public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
    notNull(session, NO_SQL_SESSION_SPECIFIED);
    notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);

    SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
    if ((holder != null) && (holder.getSqlSession() == session)) {
      if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Releasing transactional SqlSession [" + session + "]");
      }
      holder.released();
    } else {
      if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Closing non transactional SqlSession [" + session + "]");
      }
      session.close();
    }
  }

 

 

mybatis交由spring管理事务

   如果myBatis和spring集成,且spring开启了事务管理(声明式事务、注解式事务)

   myBatis会将sqlSession交给spring来管理。会在一个可能的事务方法中,将sqlSession交由spring管理。

 

  public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
    notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);

//每一次获取sqlSession。都提前从resources中获取sqlSessionHolder SqlSessionHolder holder
= (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); SqlSession session = sessionHolder(executorType, holder);
//如果spring管理了事务,则直接获取sqlSession
if (session != null) { return session; } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Creating a new SqlSession"); } //通过sqlSessionFactory 创建新的事务 session = sessionFactory.openSession(executorType); registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session); return session; }

 

posted @ 2017-04-13 17:11  qtyy  阅读(1083)  评论(0编辑  收藏  举报