為什么Mybatis DefaultSqlSession不是線程安全的

為什么Mybatis DefaultSqlSession不是線程安全的

首先在DefaultSqlSession的源碼中明確說了不是線程安全的:

/**
*
* The default implementation for {@link SqlSession}.
* Note that this class is not Thread-Safe.
*
* @author Clinton Begin
*/

我的理解主要是兩方面:

  1. 首先由于JDBC的Connection對象本身不是線程安全的,而session中又只有一個connection,所以不是線程安全的
  2. 一級緩存
    由于一級緩存是session級別的拓诸,所以如果多個線程同時使用session押赊,當(dāng)線程A進行了插入操作未完成瓶埋,但是此時線程B進行查詢并緩存了數(shù)據(jù)纲仍,這是就出現(xiàn)了一級緩存與數(shù)據(jù)庫數(shù)據(jù)不一致的問題耻矮。

對于Sessioin與Connection的關(guān)系果正,有如下代碼過程追蹤:

1炎码、通過SessionFactory創(chuàng)建session

SqlSession sqlSession = sqlSessionFactory.openSession();

2、可以追蹤代碼到org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      // 這里創(chuàng)建事務(wù)
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      // 這里將事務(wù)傳遞給執(zhí)行器Executor秋泳,這個是session執(zhí)行數(shù)據(jù)庫操作的核心
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

3潦闲、當(dāng)session執(zhí)行操作時是通過executor來進行的,繼續(xù)追蹤Executor迫皱,在SimpleExecutor中最終創(chuàng)建了Statement這個JDBC對象歉闰,而這個對象是要通過connection創(chuàng)建的。

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      // 這里創(chuàng)建statement對象
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

4卓起、繼續(xù)prepareStatement

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    // 看下面的方法
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
  }
  
  protected Connection getConnection(Log statementLog) throws SQLException {
    // 這里最終同通過創(chuàng)建Executor時傳入的transcation進行了連接獲取
    Connection connection = transaction.getConnection();
    if (statementLog.isDebugEnabled()) {
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
    } else {
      return connection;
    }
  }

5和敬、繼續(xù)看transcation的getConnection

  @Override
  public Connection getConnection() throws SQLException {
    // 這里只要有連接了就不重新打開連接了(從數(shù)據(jù)源中再次獲取)戏阅,說明只能有一個連接在一個org.apache.ibatis.transaction.Transaction中
    if (connection == null) {
      openConnection();
    }
    return connection;
  }

至此可以看到一次SqlSession的執(zhí)行最終是通過是通過事務(wù)獲取了連接昼弟,而一個session中只能有一個事務(wù),一個事務(wù)又只能有一個連接奕筐,所以一個session中只有一個connection舱痘。

以上代碼追蹤證實由于Connection的線程不安全,所以SqlSession也是線程不安全的离赫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芭逝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子笆怠,更是在濱河造成了極大的恐慌铝耻,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瓢捉,居然都是意外死亡频丘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門泡态,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搂漠,“玉大人,你說我怎么就攤上這事某弦⊥┨溃” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵靶壮,是天一觀的道長怔毛。 經(jīng)常有香客問我,道長腾降,這世上最難降的妖魔是什么拣度? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮螃壤,結(jié)果婚禮上抗果,老公的妹妹穿的比我還像新娘。我一直安慰自己奸晴,他們只是感情好冤馏,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寄啼,像睡著了一般逮光。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辕录,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天睦霎,我揣著相機與錄音,去河邊找鬼走诞。 笑死,一個胖子當(dāng)著我的面吹牛蛤高,可吹牛的內(nèi)容都是我干的蚣旱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戴陡,長吁一口氣:“原來是場噩夢啊……” “哼塞绿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恤批,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤异吻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诀浪,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡棋返,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了雷猪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睛竣。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖求摇,靈堂內(nèi)的尸體忽然破棺而出射沟,到底是詐尸還是另有隱情,我是刑警寧澤与境,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布验夯,位于F島的核電站,受9級特大地震影響摔刁,放射性物質(zhì)發(fā)生泄漏挥转。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一簸搞、第九天 我趴在偏房一處隱蔽的房頂上張望扁位。 院中可真熱鬧,春花似錦趁俊、人聲如沸域仇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暇务。三九已至,卻和暖如春怔软,著一層夾襖步出監(jiān)牢的瞬間垦细,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工挡逼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留括改,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓家坎,卻偏偏與公主長得像嘱能,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子虱疏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 主題是Mybatis一級和二級緩存的應(yīng)用及源碼分析惹骂。希望在本場chat結(jié)束后,能夠幫助讀者朋友明白以下三點做瞪。...
    余平的余_余平的平閱讀 1,327評論 0 12
  • # 前言 在java程序員的世界里对粪,最熟悉的開源軟件除了 Spring,Tomcat,還有誰呢著拭?當(dāng)然是 Mybat...
    莫那一魯?shù)?/span>閱讀 3,297評論 3 11
  • 1. 簡介 1.1 什么是 MyBatis 纱扭? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,523評論 0 4
  • 1茫死、面向?qū)ο蟮奶卣饔心男┓矫? 答:面向?qū)ο蟮奶卣髦饕幸韵聨讉€方面: -- 抽象:抽象是將一類對象的共同特征總結(jié)...
    ccc_74bd閱讀 980評論 0 1
  • 呵一口氣跪但,像霧消散。 手腳麻木是我對冬天最好的說明峦萎。 出行時屡久,不戴口罩臉會生疼。
    G無類閱讀 283評論 0 1