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 已经存在,则直接拿取

  • 相关阅读:
    Android面试题目整理与解说(一)
    Linux 6.3下安装Oracle Enterprise Cloud Control 12c
    xcode5. 安装cocos2d-x 学习中。。。
    Bootstrap组件之输入框组
    洛谷P2852 [USACO06DEC]牛奶模式Milk Patterns
    洛谷P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold
    洛谷P4051 [JSOI2007]字符加密
    洛谷P3809 【模板】后缀排序
    洛谷P2598 [ZJOI2009]狼和羊的故事
    洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6555280.html
Copyright © 2011-2022 走看看