zoukankan      html  css  js  c++  java
  • 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; }
  • 相关阅读:
    C#實現列舉DB中所有StoredProcedur
    Configure the browserJMeter
    DB 字段
    SQL Server 角色類型
    將N行數據合併成一行顯示
    性能计数器
    一千萬條以上記錄分頁數據庫優化
    SPFA静态链表优化+队列储存
    多源最短路pku1125
    图的连通性——folyd检验
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6704875.html
Copyright © 2011-2022 走看看