spring如何管理mybatis(二) ----- SqlSession的執行緒安全性

來源:互聯網
上載者:User

標籤:his   重點   tsql   oss   線程   []   bsp   .sql   dea   

  在之前的文章中我們瞭解到最終的資料庫最終操作是走的代理類的方法:

 @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 {        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);        }      }    }

我們可以看到每次都是使用getSqlSession()來擷取真是sqlsession的,而擷取的sqlSession又是DefaultSqlSession,這個類我們知道他是線程不安全的,之前使用都是採用多執行個體模式,就是每次使用都new一個,但是spring採用了更加聰明的方式可以使它不需要每次new一個也可以保持安全執行緒。

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {    
  SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); SqlSession session = sessionHolder(executorType, holder); if (session != null) { return session; } session = sessionFactory.openSession(executorType); registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session); return session; }

我們看到

TransactionSynchronizationManager.getResource(sessionFactory)

 這個方法,他的作用主要是在當前線程的交易管理中擷取一個session的持有人。

sessionHolder(executorType, holder)

 這個方法,他的作用是擷取一個session資源,並進行登記。

 如果沒有擷取到session,就會自己建立一個並執行

registerSessionHolder

   這個方法,將建立的session試圖放進當前的線程上下文中。

private static void registerSessionHolder(SqlSessionFactory sessionFactory, ExecutorType executorType,      PersistenceExceptionTranslator exceptionTranslator, SqlSession session) {    SqlSessionHolder holder;    if (TransactionSynchronizationManager.isSynchronizationActive()) {      Environment environment = sessionFactory.getConfiguration().getEnvironment();      if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {        holder = new SqlSessionHolder(session, executorType, exceptionTranslator);        TransactionSynchronizationManager.bindResource(sessionFactory, holder);        TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));        holder.setSynchronizedWithTransaction(true);        holder.requested();      } }

  我們重點看看這個方法,首先

TransactionSynchronizationManager.isSynchronizationActive()
    public static boolean isSynchronizationActive() {        return (synchronizations.get() != null);    }

這個方法主要判斷當前線程的synchronizations是不是有值的,那這個值得初始化在哪裡呢,他的初始化發生在事務攔截器中,當建立一個事務時會為當前的線程添加synchronizations,當該事務結束時會將他清空。

  

        holder = new SqlSessionHolder(session, executorType, exceptionTranslator);        TransactionSynchronizationManager.bindResource(sessionFactory, holder);        TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));        holder.setSynchronizedWithTransaction(true);        holder.requested();

接下來的就是建立一個session的持有人,然後把他綁定到當前的交易管理中,這樣只要是在該事務中的事務操作都可以使用這個sqlsession,因為他們一定是在同一線程,他們的動作一定是互斥的,這樣可以保證線程的安全性。

  綜上所述,我們可以總結下,當我們的程式被spring的交易管理時,程式中的資料庫操作可以使用同一個SqlSession,而不會產生安全執行緒問題。

  

spring如何管理mybatis(二) ----- SqlSession的執行緒安全性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.