zoukankan      html  css  js  c++  java
  • SqlsessionTemplate线程安全解密

    SqlsessionTemplate线程安全解密

    springboot中使用的是SqlsessionTemplate,而不是DefaultSqlsession,这个类是单例的,如何保证线程安全呢?

    类图

    源码解析

    org.mybatis.spring.SqlSessionTemplate#selectList(java.lang.String),委托给代理

    @Override
      public <E> List<E> selectList(String statement) {
        return this.sqlSessionProxy.<E> selectList(statement);
      }
    

    org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke,代理类核心方法

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	// 获取Sqlsession
          SqlSession sqlSession = getSqlSession(
              SqlSessionTemplate.this.sqlSessionFactory,
              SqlSessionTemplate.this.executorType,
              SqlSessionTemplate.this.exceptionTranslator);
          try {
    		  // 执行代理方法
            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);
            }
          }
        }
    

    org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)产生sqlSession方法

    public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
    
        notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
        notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);
    
        SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
    
        SqlSession session = sessionHolder(executorType, holder);
        if (session != null) {
          return session;
        }
    
        if (LOGGER.isDebugEnabled()) {
          LOGGER.debug("Creating a new SqlSession");
        }
    // 产生DefaultSqlsession
        session = sessionFactory.openSession(executorType);
    
        registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
    
        return session;
      }
    

    总结

    线程安全是通过代理来实现,代理里面每次产生了新的DefaultSqlsession来保证线程安全。

    参考

  • 相关阅读:
    Idea配置注释
    mysql省市区数据表
    php实现汉字转拼音的类
    git push时如果不再弹出用户和密码的输入提示框该怎么办
    .gitignore 忽略特殊文件无效
    vmware中CentOS7网络设置教程详解
    Tp5中配置多模块开发
    安装tp6 并使用多应用模式
    ldf和mdf文件怎么还原到sqlserver数据库
    git本地仓库与远程仓库建立连接。
  • 原文地址:https://www.cnblogs.com/seekwind/p/12600299.html
Copyright © 2011-2022 走看看