美文网首页
Mybatis SqlSession在spring中的生命周期

Mybatis SqlSession在spring中的生命周期

作者: 三斤牛肉 | 来源:发表于2019-08-26 21:19 被阅读0次

    mybatis-spring中核心类是SqlSessionTemplate:

    public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
          PersistenceExceptionTranslator exceptionTranslator) {
    
        notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
        notNull(executorType, "Property 'executorType' is required");
    
      //工厂类一般为单例
        this.sqlSessionFactory = sqlSessionFactory;
        this.executorType = executorType;
        this.exceptionTranslator = exceptionTranslator;
      //核心代理类,用SqlSessionInterceptor代理了SqlSession接口
        this.sqlSessionProxy = (SqlSession) newProxyInstance(
            SqlSessionFactory.class.getClassLoader(),
            new Class[] { SqlSession.class },
            new SqlSessionInterceptor());
      }
    
     /**
       * Proxy needed to route MyBatis method calls to the proper SqlSession got
       * from Spring's Transaction Manager
       * It also unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to
       * pass a {@code PersistenceException} to the {@code PersistenceExceptionTranslator}.
       */
      private class SqlSessionInterceptor implements InvocationHandler {
        @Override
        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);
            }
          }
        }
      }
    
    public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
    
        notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
        notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);
    
    //这里是核心,TransactionSynchronizationManager保存了事务相关上下文,都保存在ThreadLocal中
        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");
        }
    
    //如果当前线程上下文中没有sqlsession,则重新开一个
        session = sessionFactory.openSession(executorType);
    
    //这里是注册sqlsession到上下文中,不展开看了
        registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
    
        return session;
      }
    

    总结

    从上面的源码可以看出,sqlSession的生命周期是线程级别的。

    提问:

    当使用多线程去处理数据的时候,如何保证事务呢?

    相关文章

      网友评论

          本文标题:Mybatis SqlSession在spring中的生命周期

          本文链接:https://www.haomeiwen.com/subject/zcvdectx.html