7.1 二级缓存

关于二级缓存的例子,可以查看测试中的 tk.mybatis.mapper.cache.CacheTest

首先需要开启二级缓存:

  1. <!DOCTYPE configuration
  2. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  4. <configuration>
  5. <settings>
  6. <setting name="cacheEnabled" value="true"/>
  7. </settings>
  8. <!-- 其他 -->
  9. </configuration>

7.1.1 只使用接口

只用接口时,只需要加一个缓存的注解,示例如下:

  1. /**
  2. * 只有接口时,加下面的注解即可
  3. */
  4. @CacheNamespace
  5. public interface CountryCacheMapper extends Mapper<Country> {
  6. }

对缓存的详细配置可以通过该注解提供的属性进行配置。

7.1.2 接口和 XML 混合

由于 MyBatis 目前处理 XML 和 接口中的引用时存在 BUG,所以只有这里提供的一种方式进行配置。也就是在 XML 中配置 <cache/>,在接口中使用 @CacheNamespaceRef(CountryCacheRefMapper.class) 引用注解。

关于该 BUG 可以查看下面链接:

https://github.com/mybatis/mybatis-3/issues/1194

在 XML 中定义缓存:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="tk.mybatis.mapper.cache.CountryCacheRefMapper">
  6. <cache/>
  7. <select id="selectById" resultType="tk.mybatis.mapper.base.Country">
  8. select * from country where id = #{id}
  9. </select>
  10. </mapper>

在接口中配置注解引用:

  1. @CacheNamespaceRef(CountryCacheRefMapper.class)
  2. //或者 @CacheNamespaceRef(name = "tk.mybatis.mapper.cache.CountryCacheRefMapper")
  3. public interface CountryCacheRefMapper extends Mapper<Country> {
  4. /**
  5. * 定义在 XML 中的方法
  6. *
  7. * @param id
  8. * @return
  9. */
  10. Country selectById(Integer id);
  11. }

@CacheNamespaceRef 指定的是缓存的 namespace,就是 XML 中 <mapper> 中的 namespace 属性。

7.1.3 潜在的问题

通用 Mapper 中部分 insert, update 方法使用了 @Options 注解,在 4.0 版本中 update 方法都去掉了这个注解,但是部分 insert 必须保留。

存在 @Options 注解的方法:

  1. tk.mybatis.mapper.common.special.InsertListMapper

    • int insertList(List<? extends T> recordList);
  2. tk.mybatis.mapper.common.special.InsertUseGeneratedKeysMapper

    • int insertUseGeneratedKeys(T record);
  3. tk.mybatis.mapper.common.sqlserver.InsertMapper

    • int insert(T record);
  4. tk.mybatis.mapper.common.sqlserver.InsertSelectiveMapper

    • int insertSelective(T record);

这 4 个方法都是特殊的方法,不是 Mapper<T> 接口中包含的两个 insert 方法。

MyBatis 中的 @Options 注解在 3.3.x 版本和 3.4.0+ 后的版本中,对 flushCache 方法定义不同,这就导致通用 Mapper 中无法直接配置改属性,在 3.3.x 等低版本中,该属性默认 false,因此执行 insert 后不会清除一二级缓存。在高版本中不存在该问题。

因此如果要使用二级缓存,建议 MyBatis 使用比较新的版本,否则需要考虑使用 insert 后可能查询不到的问题。

Options 注解中的 flushCache 区别如下:

3.3.x 以及更旧的版本中:

  1. boolean flushCache() default false;

3.4.0+中:

  1. /**
  2. * The options for the {@link Options#flushCache()}.
  3. * The default is {@link FlushCachePolicy#DEFAULT}
  4. */
  5. public enum FlushCachePolicy {
  6. /** <code>false</code> for select statement; <code>true</code> for insert/update/delete statement. */
  7. DEFAULT,
  8. /** Flushes cache regardless of the statement type. */
  9. TRUE,
  10. /** Does not flush cache regardless of the statement type. */
  11. FALSE
  12. }
  13. FlushCachePolicy flushCache() default FlushCachePolicy.DEFAULT;

很显然,在 3.4.0+ 中的定义更合理,所以如果使用二级缓存,建议升级到比较新的版本。