mybatis----缓存

查询缓存

mybaits提供了一级缓存和二级缓存,用于减轻数据压力,提高数据库性能。。

1.1 什么是一级缓存

我们创建出一个SqlSession对象表示一次数据库会话,在这次会话中,我们有可能好几次执行一样的查询语句,若是每次都去访问数据库,那么就会造成数据库资源的浪费,所以mybatis引入一级缓存,在SqlSession中建立一个缓存(数据结构为hashmap),每次查询先去查看缓存中是否有,有的话就把结果返回,没有的话再去查询数据库并将查到的结果缓存起来。

需要注意的是,不同的sqlSession对象之间的缓存数据区域是互相不影响的。

SqlSession只是对外的接口,真正执行各种数据库操作的是Executor执行器(也是一个接口)。当创建了一个SqlSession对象时,MyBatis会为这个SqlSession对象创建一个新的Executor执行器,而缓存信息就被维护在这个Executor执行器中。MyBatis将缓存和对缓存相关的操作封装成了Cache接口中。
SqlSession、Executor、Cache之间的关系如下列类图所示:


sqlSession级别的一级缓存实际上就是使用PerpetualCache维护的。

1.2一级缓存的生命周期

  1. 开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉;

  2. 如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,此时一级缓存不可用;

  3. 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是PerpetualCache对象仍可使用;

4.SqlSession中执行了一个更新增加删除操作 ,都会清空全部PerpetualCache对象的数据,但是该对象可以继续使用;

1.3 一级缓存的工作流程

  1. 对于某个查询,根据statementId,params,rowBounds来构建一个key值;

  2. 根据这个key值去缓存Cache中判断是否命中缓存;

  3. 如果命中,则直接将缓存结果返回;

  4. 如果没命中:

     4.1  去数据库中查询数据,得到查询结果;
    
     4.2  将key和查询到的结果分别作为key,value对存储到Cache中;
    
     4.3. 将查询结果返回;
    
  5. 结束。

1.4 如何判断两次查询是一样的

从实现来看,mybatis是利用key是否相同来判断两次查询是否相同的,而key是由statementId,params,rowBounds这三项构建的。

其中,statementId决定带参数的sql(有“?”占位符的的sql或是需要拼接字符串的sql语句),params决定占位符传入的参数或是要拼接的字符串,rowBounds决定查询的结果集的范围(也就是 limit x,y ),这三个参数决定了最终的sql,也就是说当这个最终的sql一样时,那么就判断这两次是一样查询。

1.5 真正应用

真正开发的时候,sqlSession是用spring管理的,而mapper是在service里面调用,在这种情况下,什么时候会用到一级缓存呢?
实际上,在一个service里,只有一个sqlSession,在service结束之后才会关闭这个sqlSession,sqlSession关闭则缓存清空。所以一个service函数里面多次调用mapper是会走一级缓存的,而多次调用service则互不影响。


2.1 什么是二级缓存

二级缓存是namespace级别的缓存,多个SqlSession可以共用二级缓存,不同sqlSession操作同一个namespace下的同一个sql,就会走二级缓存。


二级缓存工作流程

2.2开启二级缓存

在SqlMapConfig.xml里开启mybatis的全局二级缓存开关,默认是开启的:


    

还需要在要二级缓存开启的mapper.xml里面开启开关:

2.3 二级缓存与一级缓存区别

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个namespace下的二级缓存区域。

2.4 测试二级缓存

需要关闭sqlSession1才会把内容写到缓存,sqlSession2才会读到:


在sqlSession1和sqlSession2之间加入以下代码,为了测试更新操作是否清空缓存:


2.5 二级缓存参数设置

设置某些sql禁用二级缓存

在statement中设置useCache=false可以禁用当前select语句使用二级缓存,即每次查询都会发出sql去查询数据库。默认情况是true,即该sql使用二级缓存。