MyBatis 一级缓存与二级缓存

本文转载自:Mybatis一级缓存与二级缓存的区别你知道吗,作者 Java小叮当

MyBatis 缓存是什么

缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存可以避免频繁与数据库进行交互,从而提高查询响应速度。

MyBatis 提供了对缓存的支持,分为一级缓存和二级缓存,如下图所示:
image

我们先大致了解下 MyBatis 一级缓存与 MyBatis 二级缓存:

  • 一级缓存:SqlSession 级别的缓存,缓存的数据只在 SqlSession 内有效。

  • 二级缓存: mapper 级别的缓存,同一个 namespace 公用这一个缓存,所以对 SqlSession 是共享的,二级缓存需要我们手动开启。

下面我们再分别详解两者的原理与区别。

MyBatis 一级缓存

1. 为什么需要 MyBatis 一级缓存

当我们使用 MyBatis 进行数据库的操作时候,会创建一个 SqlSession 来进行一次数据库的会话,会话结束则关闭 SqlSession 对象。

可能在一次 sql 会话中我们多次执行完全相同的查询语句,如果每次执行都查询一次数据库,这是没有必要的,是对系统资源的浪费。

为了解决这个问题,MyBatis 对每一次会话都添加了缓存操作,不用相同的 SQL 每次都需要查询数据库,这就是 MyBatis 一级缓存的作用。

这里我有个思考:假如有并发问题,那应该在代码层面控制并发,而不是考虑一级缓存是不是会带来脏数据。

2. MyBatis 一级缓存的实现

我们知道对 SqlSession 的操作,MyBatis 内部都是通过 Executor 来执行的,Executor 的生命周期和 SqlSession 是一致的。

MyBatis 在 Executor 中创建了本地缓存(一级缓存),如下图所示:
image

大致的流程如下:

  1. 第一次查询用户 id 信息,先去缓存中查询是否有,如果没有,从数据库中查询用户信息,得到用户信息后在将用户信息储存到一级缓存中。在 SqlSession 中执行 commit 操作(插入、更新、删除)会清空 SqlSession 中的一级缓存,保证缓存中始终保存的是最新的信息,避免脏读。

  2. 第二次查询用户 id 信息,先去缓存中查询,如缓存中有,直接从缓存中获取。

注意:两次查询须在同一个 Sqlsession 中完成,否则将不会走 MyBatis 的一级缓存。

在 MyBatis 与 Spring 进行整合开发时,事务控制在 service 中进行,重复调用两次 servcie 将不会走一级缓存,因为在第二次调用时 session 方法结束,SqlSession 就关闭了。

3. MyBatis 一级缓存配置

MyBatis 一级缓存的范围有 SESSION 和 STATEMENT 两种,默认是 SESSION。

如果不想使用一级缓存,可以把一级缓存的范围指定为 STATEMENT,这样每次执行完一个 Mapper 中的语句后都会将一级缓存清除。

如果需要更改一级缓存的范围,可以在 MyBatis 的配置文件中,在下通过 localCacheScope 指定。

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

MyBatis 二级缓存

1. 为什么需要 MyBatis 二级缓存?

MyBatis 一级缓存最大的共享范围就是一个 SqlSession 内部,那么如果多个 SqlSession 需要共享缓存,则需要开启二级缓存。

2. MyBatis 二级缓存的实现

开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询,具体的工作流程如下所示。
image

二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被多个 SqlSession 共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

MyBatis 是默认关闭二级缓存的,因为对于增删改操作频繁的话,那么二级缓存形同虚设,每次都会被清空缓存。

总结

  1. MyBatis 缓存是执行 SQL 优先从缓存中查询,查询不到再查数据库。分为一级缓存和二级缓存。
  2. MyBatis 默认开启一级缓存,一级缓存的作用域是 SqlSession。即在一个 SqlSession 中相同的 SQL 第二次从缓存获取结果。当两次查询中间执行了 commit 操作即事务提交,SqlSession 的缓存会被清空。
  3. MyBatis 的缓存使用一个HashMap,key 为hashcode+statementId+sql语句。value 为查询出来的结果集映射成的 Java 对象。
  4. MyBatis 二级缓存是默认不开启的,作用于一个 Application,是 Mapper 级别的,多个 SqlSession 使用同一个 Mapper 的 sql 就能够使用二级缓存。
posted @ 2023-06-06 16:11  狭路相逢  阅读(400)  评论(0)    收藏  举报