中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Mybatis中緩存的方式有哪些

發布時間:2021-01-18 15:15:23 來源:億速云 閱讀:162 作者:Leah 欄目:開發技術

本篇文章給大家分享的是有關Mybatis中緩存的方式有哪些,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

一級緩存

通過查看源碼可知,一級緩存是綁定sqSsession中的,所以每次查詢sqlSession不同就失效,相同的sqlSession可以使用一級緩存。

mybatis默認sqlsession:org.apache.ibatis.session.defaults.DefaultSqlSession

構造方法中傳入executor(查詢執行對象)

 public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
  this.configuration = configuration;
  this.executor = executor;
  this.dirty = false;
  this.autoCommit = autoCommit;
 }

executor中攜帶一級緩存成員:

 protected BaseExecutor(Configuration configuration, Transaction transaction) {
  this.transaction = transaction;
  this.deferredLoads = new ConcurrentLinkedQueue<>();
  this.localCache = new PerpetualCache("LocalCache"); //默認一級緩存
  this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
  this.closed = false;
  this.configuration = configuration;
  this.wrapper = this;
 }

查詢使用一級緩存邏輯

org.apache.ibatis.executor.BaseExecutor.query()

 public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
  ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
  
  List<E> list;
  try {
   queryStack++;
   	//localCache 一級緩存
   list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
    //先從一級緩存中獲取,key是通過sql語句生成
   if (list != null) {
    handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
   } else {
    // 如果緩存中沒有 才從數據庫查詢
    list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
   }
  } finally {
   queryStack--;
  }
  return list;
 }

 //從數據庫讀取數據
 private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
  List<E> list;
  localCache.putObject(key, EXECUTION_PLACEHOLDER);
  try {
   list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
  } finally {
   localCache.removeObject(key);//將一級緩存清除
  }
  localCache.putObject(key, list);//返回查詢結果之前,先放入一級緩存 刷新
  if (ms.getStatementType() == StatementType.CALLABLE) {
   localOutputParameterCache.putObject(key, parameter);
  }
  return list;
 }

二級緩存

二級緩存mapper中的,默認是開啟的,但需要在映射文件mapper.xml中添加<cache/>標簽

<mapper namespace="userMapper">
	<cache/><!-- 添加cache標簽表示此mapper使用二級緩存 -->
</mapper>

配置false可以關閉二級緩存

二級緩存的解析

org.apache.ibatis.builder.xml.XMLMapperBuilder

 private void configurationElement(XNode context) {
  try {
   //...
   cacheElement(context.evalNode("cache")); //解析cache標簽
  } catch (Exception e) {
   throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
  }
 }

 private void cacheElement(XNode context) {
  if (context != null) { // if hava cache tag 如果有cache標簽才執行下面的邏輯
   String type = context.getStringAttribute("type", "PERPETUAL");
   Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
   String eviction = context.getStringAttribute("eviction", "LRU");
   Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
   Long flushInterval = context.getLongAttribute("flushInterval");
   Integer size = context.getIntAttribute("size");
   boolean readWrite = !context.getBooleanAttribute("readOnly", false);
   boolean blocking = context.getBooleanAttribute("blocking", false);
   Properties props = context.getChildrenAsProperties();
   builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);//建立二級緩存
  }
 }

org.apache.ibatis.builder.MapperBuilderAssistant.useNewCache():

 public Cache useNewCache(Class<? extends Cache> typeClass,
   Class<? extends Cache> evictionClass,
   Long flushInterval,
   Integer size,
   boolean readWrite,
   boolean blocking,
   Properties props) {
  Cache cache = new CacheBuilder(currentNamespace)
    .implementation(valueOrDefault(typeClass, PerpetualCache.class))
    .addDecorator(valueOrDefault(evictionClass, LruCache.class))
    .clearInterval(flushInterval)
    .size(size)
    .readWrite(readWrite)
    .blocking(blocking)
    .properties(props)
    .build();
  configuration.addCache(cache);//二級緩存賦值,如果cache標簽為空,不會執行此方法,currentCache為空
  currentCache = cache; 
  return cache;
 }

 在映射文件mapper中如果沒有cache標簽,不會執行上面的useNewCache方法,cache為null,就不會使用二級緩存(相當于失效)。

查詢使用二級緩存邏輯

org.apache.ibatis.executor.CachingExecutor :

 @Override
 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
   throws SQLException {
  Cache cache = ms.getCache(); 
  if (cache != null) {//如果二級緩存對象不為空 嘗試在二級緩存中獲取(沒有cache標簽此對象就是空)
   flushCacheIfRequired(ms);
   if (ms.isUseCache() && resultHandler == null) {
    ensureNoOutParams(ms, boundSql);
    @SuppressWarnings("unchecked")
    List<E> list = (List<E>) tcm.getObject(cache, key); //從二級緩存中獲取數據
    if (list == null) {
     list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); //如果為空,使用delegate查詢(BaseExecutor)
     tcm.putObject(cache, key, list); // 查詢結果保存到二級緩存
    }
    return list;
   }
  }
  return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
 }

二級緩存和一級緩存不用想,數據庫的數據被修改是要清空緩存的,不然數據有誤,至于怎么清空,是另一套邏輯了,mapper中的cache標簽可以配置一些參數,比如緩存定期清空。

一級二級緩存先后順序

mybatis默認是先查詢二級緩存,沒有,再查看一級緩存,都為空,最后查詢數據庫

以上就是Mybatis中緩存的方式有哪些,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

龙井市| 沿河| 赫章县| 新巴尔虎右旗| 莆田市| 大余县| 吉首市| 高雄县| 凉山| 湖北省| 临沂市| 威信县| 洪湖市| 枣强县| 金坛市| 武穴市| 普格县| 卓尼县| 溧水县| 泗洪县| 新民市| 兴城市| 双城市| 抚顺县| 共和县| 龙里县| 确山县| 侯马市| 大同市| 云南省| 穆棱市| 秦安县| 美姑县| 大石桥市| 新营市| 越西县| 柏乡县| 布拖县| 读书| 高密市| 新平|