Mybatis之一級緩存(localCache緩存)簡析

注:Mybatis的版本是3.5.0。java

1.LocalCache(一級緩存)

    先上一張圖數據庫

               

                                                      圖1 Mybatis查詢時使用LocalCacheapache

    LocalCache,也被稱爲一級緩存,有以下特色:緩存

  •     它的生命週期與SqlSession一致。
  •     底層用HashMap實現,沒有緩存內容更新和過時。
  •     有個多個SqlSession時,且有數據庫寫,會出現髒讀的狀況,一級緩存慎用,或者將Scope設置爲Statement。

    LocalCacheScope有倆個值,以下List-1所示session

    List-1 LocalCacheScope的值有枚舉值fetch

package org.apache.ibatis.session;

/**
 * @author Eduardo Macarron
 */
public enum LocalCacheScope {
    SESSION, STATEMENT
}

    Configuration中localCacheScope默認值是SESSION,以下List-2所示this

    List-2 Configuration的屬性localCacheScope默認值是SESSIONspa

package org.apache.ibatis.session;
.....

/**
 * @author Clinton Begin
 */
public class Configuration {
  ......
  protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
  ......

    

    爲何說LocalCache生命週期與SqlSession一致,如List-3所示:code

    List-3 DefaultSqlSessionFactory的openSessionFromDataSource和openSessionFromConnection對象

package org.apache.ibatis.session.defaults;

......

/**
 * @author Clinton Begin
 */
public class DefaultSqlSessionFactory implements SqlSessionFactory {

 ......

 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  Transaction tx = null;
  try {
    final Environment environment = configuration.getEnvironment();
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    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();
  }
}

  private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
      boolean autoCommit;
      try {
        autoCommit = connection.getAutoCommit();
      } catch (SQLException e) {
        // Failover to true, as most poor drivers
        // or databases won't support transactions
        autoCommit = true;
      }      
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      final Transaction tx = transactionFactory.newTransaction(connection);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

 ......

    List-3中的方法openSessionFromDataSource和方法openSessionFromConnection中的configuration.newExecutor(tx, execType)的實現以下List-4所示。每次實例化一個DefaultSqlSession時,都會實例化一個SimpleExecutor,而用於一級緩存的localCache就在BaseExecutor中,BaseExecutor是SimpleExecutor的父類。因此當SqlSession對象被銷燬時,它的Executor也被銷燬,因此localCache也被銷燬。

    List-4 newExecutor中默認狀況下新建SimpleExecutor

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
  executorType = executorType == null ? defaultExecutorType : executorType;
  executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
  Executor executor;
  if (ExecutorType.BATCH == executorType) {
    executor = new BatchExecutor(this, transaction);
  } else if (ExecutorType.REUSE == executorType) {
    executor = new ReuseExecutor(this, transaction);
  } else {
    executor = new SimpleExecutor(this, transaction);
  }
  if (cacheEnabled) {
    executor = new CachingExecutor(executor);
  }
  executor = (Executor) interceptorChain.pluginAll(executor);
  return executor;
}

   

2.參考

    1.https://www.jianshu.com/p/c553169c5921,這篇博客寫的挺好的。

    2.Mybatis源碼,去Github上下載。

相關文章
相關標籤/搜索