mybatis缓存的设计

Posted JsonSun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis缓存的设计相关的知识,希望对你有一定的参考价值。

继续用提问的方式来看Mybatis的缓存设计。

1、Mybatis如何开启缓存

Mybatis对查询结果进行缓存,所以缓存的对象为具体的Statement

通过在Statement上是否使用缓存来启用。

<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"  fetchSize="5" statementType="PREPARED" useCache="true" >
useCache默认值为true

2、谁持有缓存?

 Mybatis中有两个对象持有缓存。

CachingExecutor以及BaseExecutor

   

CachingExecutor和SimpleExecutor的关系是持有的关系
public class CachingExecutor implements Executor {

  private final Executor delegate;
  private final TransactionalCacheManager tcm = new TransactionalCacheManager();

 

 

3、缓存何时开启?

  当开启Mapper级别的缓存时,缓存被开启

  缓存是一直开启的

4、缓存何时被命中?

 

  5、缓存清空的时机

  ①数据库发生变更(update,insert,delete),即使事物没有提交,缓存失效

  ②对于相同命名空间Mapper的缓存,多个线程,并发使用相同Mapper的不同语句,任意一个执行事物提交,可导致缓存失效

  实际效果:

  缓存 会和mysql的rr隔离级别一致,不会导致幻读(read uncommited)

  缓存 在不使用缓存的时候,有效

  验证缓存

          

  使用代码验证:

  两次查询,只访问了数据库1次.第二次不再请求数据库

    

  一次查询,一次更新(不提交),一次查询.缓存失效,出发了两次数据库查询。

      

  缓存的验证

  不配置缓存时,验证不同的sqlSesiion缓存是否通用

  触发2次数据库访问

    

   配置缓存参数

<settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
  <cache/>

   

  结果出乎意料,缓存竟然没有命中。分析下原因:

   

  即使打开了缓存,首先也是保存在事物级别的缓存里,TransactionalCache里.

  只有当实物提交时,才会真正将缓存转移到delegate中(delegate是真正的Mapper之间公用的缓存)

  调整代码,后缓存生效。

  

  让人不理解的,出于什么目的,要commit后,再共享?

  如果在某一秒,有10个并发共同访问数据库。那他们会同时产生10个连接,并不会命中。  

6、Mybatis缓存设计的目的

  简单,不配置也可以使用。用与在一个sqlSession中多次使用相同条件多次查询。

7、Mybatis缓存设计的目的

  增强版,也支持事物级别的缓存,同时支持不同sqlSession之间的共享。扩大可缓存的可用性。

 

以上是关于mybatis缓存的设计的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis缓存设计

mybatis缓存的设计

MyBatis缓存机制的设计与实现

干货分享 | MyBatis实战缓存机制设计与原理解析

Mybatis关于复杂的SQL查询的处理&Mybatis的缓存机制

Mybatis关于复杂的SQL查询的处理&Mybatis的缓存机制