Mybatis一级缓存二级缓存使用总结

Mybatis缓存简单使用

MyBatis中的缓存分为一级缓存和二级缓存,一级缓存又被称为 SqlSession 级别的缓存,二级缓存又被称为表级缓存。

一级缓存

一级缓存是 SqlSession级别 的缓存。在操作数据库时需要构造 sqlSession 对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的 sqlSession 之间的缓存数据区域(HashMap)是互相不影响的。用一张图来表示一下一级缓存,其中每一个 SqlSession 的内部都会有一个一级缓存对象。

在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis 提供了一级缓存的方案优化这部分场景,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能

一级缓存使用条件

  1. 必须是相同的SQL和参数
  2. 必须是相同的会话
  3. 必须是相同的namespace 即同一个mapper
  4. 必须是相同的statement 即同一个mapper 接口中的同一个方法
  5. 查询语句中间没有执行session.clearCache() 方法
  6. 查询语句中间没有执行 insert update delete 方法(无论变动记录是否与 缓存数据有无关系)

一级缓存失效条件:

  1. 查询中途有增删改操作
  2. 不同SqlSession会话
  3. 同一SqlSession 使用不同的查询条件
  4. 使用 sqlSession.clearCache() 手动清理缓存

二级缓存

业务系统中存在很多的静态数据如,字典表、菜单表、权限表等,这些数据的特性是不会轻易修改但又是查询的热点数据。一级缓存针对的是同一个会话当中相同SQL,并不适合这情热点数据的缓存场景。为了解决这个问题引入了二级缓存,它脱离于会话之外。

查询流程:二级缓存->一级缓存->数据库

注意!!! 会话关闭之后才会触发缓存!

图中namespace1 namespace2所在灰色区域,就是二级缓存!

开启二级缓存方式:

在mapper接口上,加@CacheNamespace注解

//使用示例:
@CacheNamespace()
public interface LabelMapper {
    @Select("select * from t_label where id =#{id}")
    Label getById(Integer id);
}

@CacheNamespace注解属性说明

@CacheNamespace(
        implementation = PerpetualCache.class, //  缓存实现 Cache接口 实现类
        eviction = LruCache.class,// 缓存算法
        flushInterval = 60000, // 刷新间隔时间 毫秒
        size = 1024,   // 最大缓存引用对象
        readWrite = true, // 是否可写
        blocking = false  // 是否阻塞
)

二级缓存使用条件:

  1. 当会话提交或关闭之后,才会填充二级缓存
  2. 必须是在同一个命名空间之下
  3. 必须是相同的statement 即同一个mapper接口中的同一个方法
  4. 必须是相同SQL语句和参数
  5. 如果readWrite = true(@CacheNamespace 注解的参数,默认就是true),实体对象必须实现Serializable接口

二级缓存清除条件:

  1. 只有修改会话提交之后,才会执行清空操作
  2. 任何一种增删改操作,都会清空整个namespace中的缓存
  3. xml配置通过标签开启的缓存,是另外一个namespace的缓存,所以不会命中

是否应该使用二级缓存?

那么究竟应该不应该使用二级缓存呢?先来看一下二级缓存的注意事项:

  1. 缓存是以namespace为单位的,不同namespace下的操作互不影响。
  2. insert,update,delete操作会清空所在namespace下的全部缓存。
  3. 通常使用MyBatis Generator生成的代码中,都是各个表独立的,每个表都有自己的namespace
  4. 多表操作一定不要使用二级缓存,因为多表操作进行更新操作,一定会产生脏数据。

如果你遵守二级缓存的注意事项,那么你就可以使用二级缓存。

但是,如果不能使用多表操作,二级缓存不就可以用一级缓存来替换掉吗?而且二级缓存是表级缓存,开销大,没有一级缓存直接使用 HashMap 来存储的效率更高,所以二级缓存并不推荐使用

posted @ 2021-06-08 16:32  君子坐而论道  阅读(231)  评论(1编辑  收藏  举报