https://www.cnblogs.com/juniorMa/p/13933192.html
在上一篇中,講到一個非常重要的知識點,那就是每一個mapper對象的代理類執行方法的時候,都是每次都會new 一個SqlSession出來
但是我當時還有兩個疑問
1 在SqlSessionInterceptor中我沒有發現執行close的地方
2 為什么每次獲取sqlsession的時候,判斷ThreadLocal里面的緩存都是null呢?
經過不懈的努力,終於找到了原因,那就是由於使用了Spring提供的事務,這些資源的釋放都是事務做的
代碼在
SqlSessionUtils的內部類 SqlSessionSynchronization 的方法 @Override public void beforeCompletion() { // Issue #18 Close SqlSession and deregister it now // because afterCompletion may be called from a different thread if (!this.holder.isOpen()) { if (logger.isDebugEnabled()) { logger.debug("Transaction synchronization deregistering SqlSession [" + this.holder.getSqlSession() + "]"); } TransactionSynchronizationManager.unbindResource(sessionFactory); this.holderActive = false; if (logger.isDebugEnabled()) { logger.debug("Transaction synchronization closing SqlSession [" + this.holder.getSqlSession() + "]"); } this.holder.getSqlSession().close(); } }
AbstractPlatformTransactionManager
private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { prepareForCommit(status); triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; boolean globalRollbackOnly = false;
protected final void triggerBeforeCompletion(DefaultTransactionStatus status) { if (status.isNewSynchronization()) { if (status.isDebug()) { logger.trace("Triggering beforeCompletion synchronization"); } TransactionSynchronizationUtils.triggerBeforeCompletion(); } }
public static void triggerBeforeCompletion() { for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) { try { synchronization.beforeCompletion(); } catch (Throwable tsex) { logger.error("TransactionSynchronization.beforeCompletion threw exception", tsex); } } }
其實怎么做原因也很明顯,只有每次都new,每次都釋放,才能保證多線程不報錯