image.png

一级缓存

Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。
也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。

一级缓存的范围有SESSIONSTATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。
如果需要更改一级缓存的范围,可以在Mybatis的配置文件中,在下通过localCacheScope指定,建议不需要修改。

  1. <setting name="localCacheScope" value="STATEMENT"/>

当Mybatis整合Spring后,直接通过Spring注入Mapper的形式,如果不是在同一个事务中每个Mapper的每次查询操作都对应一个全新的SqlSession实例,这个时候就不会有一级缓存的命中,但是在同一个事务中时共用的是同一个SqlSession。如有需要可以启用二级缓存。

二级缓存

二级缓存是namespace级别的,默认不开启。默认二级缓存的粒度是Mapper级别的,但是如果在同一个Mapper文件中某个查询不想使用二级缓存的话,就需要对缓存的控制粒度更细。
在select标签中设置useCache=false,可以禁用当前select语句的二级缓存,即每次查询都是去数据库中查询,默认情况下是true,即该statement使用二级缓存。
通过flushCache属性,可以控制select、insert、update、delete标签是否属性二级缓存
image.png

第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。 第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。

如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。

二级缓存应用场景

对于访问多的查询请求并且用户对查询结果实时性要求不高,可采用二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析 sql,电话账单查询 sql 等。

实现方法:
通过设置刷新间隔时间,由 mybatis 每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔 flushInterval。
局限性是对细粒度的数据级别的缓存实现不好,比如如下需求,对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查到最新的商品信息,此时如果使用二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为二级缓存区域是以 mapper 为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空,解决此类问题需要在业务层根据需求对数据有针对性缓存

一级缓存和二级缓存的区别

二级缓存的范围更大,多个 sqlSession 可以共享一个 mapper 的二级缓存区域,每个 mapper 有自己的二级缓存区域(按 namespace 分),每个 namespace 的 mapper 都有一个二级缓存区域,两个 mapper 的 namespace 若相同,则这两个 mapper 执行sql 查询到的数据将存在相同的二级缓存区域中。