zoukankan      html  css  js  c++  java
  • myBatis 切换数据源(spring事务)理解

    1. mybatis (SqlSessionTemplate)的动态代理

      a) sqlSession的结构

      

      b)SqlSession 结构

    public class SqlSessionTemplate implements SqlSession {
      //代理对象 ------1
      private final SqlSession sqlSessionProxy;
      /**
       *//构造方法 --------2
       */
      public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
          PersistenceExceptionTranslator exceptionTranslator) {
        //利用jdk的动态代理,生成sqlSessionProxy的代理对象--------3
        this.sqlSessionProxy = (SqlSession) newProxyInstance(
            SqlSessionFactory.class.getClassLoader(),
            new Class[] { SqlSession.class },
            new SqlSessionInterceptor());
      }
    
      /**
       */
      @Override
      public <T> T selectOne(String statement) {
        //代用代理对象的目标方法,触发代理对象的产生---------4
        return this.sqlSessionProxy.<T> selectOne(statement);
      }
    
      /**
       */
      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的目标方法,proxy没有执行--------5
            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);
            }
          }
        }
      }
    
    } 

    2.没有事务:切换数据源(成功切换数据源)

      a)代理对象执行目标时,切换数据源时 (栈结构)

     

      b) 在DataSourceUtils 中,判断conHolder是否为空,

    3.存在事务:切换数据源(不会切换数据源)

      a)  在执行目标方式时,被spring拦截,检查是否存在事务,(存在事务,调用doBegin方法,为事务准备链接conncetion)

     

      b) 代理对象sqlSessionTemple 执行目标方法中,在DataSourceUtils 中判断connection 已经存在,则直接拿取

  • 相关阅读:
    jquery获取父元素或父节点的方法
    JS省份联级下拉框
    全国各省、市名称(包括县级市)
    让Vs2010支持 Css3+HTML5
    Sql Server 事务/回滚
    Windows.Forms Panel 动态加载用户控件 UserControl
    C/C++ 运算符 & | 运算
    WPF
    SQL Server 数据库定时自动备份【转】
    如何编写更棒的代码:11个核心要点
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6555280.html
Copyright © 2011-2022 走看看