MyBatis:缓存配置

使用缓存可以使应用更快地获取数据,避免频繁的数据库交互。MyBatis 作为持久化框架,提供了非常强大的查询缓存特性。

一般提到 MyBatis 缓存的时候,都是指二级缓存。一级缓存(也叫本地缓存)默认会启用,并且不能控制,因此很少会提到。

MyBatis 的一级缓存存在于 SqlSession 的生命周期中,在同一个 SqlSession 中查询时,MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map 对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中已经存在该键值时,则会返回缓存中的对象。

举例说明一级缓存是如何发挥作用的:

  1. 打开 SqlSession
  2. 查询 id 为 20 的 user1
  3. 修改 user1 的 name 为 New Name
  4. 查询 id 为 20 的 user2
  5. 关闭 SqlSession
  6. 重新打开 SqlSession
  7. 查询 id 为 20 的 user2
  8. 删除一个 id 为 22 的 user
  9. 查询 id 为 20 的 user3
  10. 关闭 SqlSession

第 2 步查询和第 4 步查询是同一个对象,第 4 步是从一级缓存中查询到的。在同一个 SqlSession 中查询时,MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map 对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中已经存在该键值时,则会返回缓存中的对象。 在第 7 步又会重新从数据库查询。

一级缓存中的对象和我们得到的结果是同一个对象,反复使用相同参数执行同一个方法时,总是返回同一个对象。

如果在方法上添加了 flushCache="true" ,那么就会在查询数据前清空当前的一级缓存。需要注意的是,任何和 insert update delete 操作都会清空一级缓存,再次查询时就会执行数据库查询。

二级缓存可以理解为存在于 SqlSessionFactory 的生命周期中。二级缓存是在 MyBatis 的全局配置 setting 中有一个参数 cacheEnabled,可以在 mybatis-config.xml 中添加如下代码:

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

MyBatis 的二级缓存是和命名空间绑定的,即二级缓存需要配置在 Mapper.xml 映射文件中,或者配置在 Mapper.java 接口中。在映射文件中,命名空间就是 xml 根节点 mapper 的 namespace 属性。在 Mapper 接口中,命名空间就是接口的全限定名称。

<mapper namespace="com.start.mybatis.mapper.SysUserMapper">
    <cache/>
</mapper>

其中 cache 有多个可以配置的属性,可查阅文档。

举个例子说明二级缓存是怎么起作用的:

  1. 打开 SqlSession
  2. 查询 id 为 20 的 role1
  3. 查询 id 为 20 的 role2
  4. 关闭 SqlSession
  5. 重新打开 SqlSession
  6. 再次查询 role2
  7. 查询 id 为 20 的 role3
  8. 关闭 SqlSession

第 3 步中查询使用的是一级缓存,返回同一个实例。第 4 步关闭 SqlSession 时,SqlSession 才会保存查询数据到二级缓存中,在这之后二级缓存才有了缓存数据。第 6 步和第 7 步均是查的二级缓存,这两步查询的结果都是反序列化得到的结果,所以它们不是相同的实例。在这一部分中,这两个实例是读写安全的,其属性不会相互影响。

MyBatis 默认提供的缓存实现是基于 Map 实现的内存缓存,已经可以满足基本的应用。但是当需要缓存大量的数据时,不能仅仅通过提高内存来使用 MyBatis 的二级缓存,还可以选择一些类似 EhCache 的缓存框架或 Redis 缓存数据库等工具来保存 MyBatis 的二级缓存数据。

posted @ 2019-08-28 17:20  colin220  阅读(177)  评论(0编辑  收藏  举报