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

  • 相关阅读:
    HAproxy 1.5 dev14 发布
    IBM/DW 使用 Java 测试网络连通性的几种方法
    Skype 4.1 Linux 发布,支持微软帐号登录
    Dorado 7.1.20 发布,Ajax的Web开发平台
    Aspose.Slides for Java 3.0 发布
    开发版本 Wine 1.5.18 发布
    BitNami Rubystack 开始支持 Ruby 2.0
    XWiki 4.3 正式版发布
    Silverlight实例教程 Out of Browser的Debug和Notifications窗口
    Silverlight实例教程 Out of Browser与Office的互操作
  • 原文地址:https://www.cnblogs.com/chihirotan/p/6555280.html
Copyright © 2011-2022 走看看