• 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来保证线程安全。

    参考

  • 相关阅读:
    YouTube视频搬运核心技术公布,月赚3万美金
    如何发掘各种暴利的赚钱项目,如何知道别人在干什么赚钱
    新手操作孕妇防辐射服暴利项目,也能日入500+
    最有效的赚钱方法,只有100元如何赚到10万?
    利用音频平台日引1000宝妈粉,轻松日赚500+
    微信小程序的另类玩法,新手也能日赚一千
    手把手教你如何复制暴利项目
    通过小红书精准引流女性粉丝,日赚1000+的网赚项目
    Android客户端与服务器的交互(增删改查)之干货篇(内含代码)
    linux下安装redis
  • 原文地址:https://www.cnblogs.com/seekwind/p/12600299.html
Copyright © 2020-2023  润新知