Skip to content

7.1.cache

isea533 edited this page Aug 5, 2018 · 4 revisions

7.1 二级缓存

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

首先需要开启二级缓存:

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <!-- 其他 -->
</configuration>

7.1.1 只使用接口

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

/**
 * 只有接口时,加下面的注解即可
 */
@CacheNamespace
public interface CountryCacheMapper extends Mapper<Country> {

}

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

7.1.2 接口和 XML 混合

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

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

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

在 XML 中定义缓存:

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

在接口中配置注解引用:

@CacheNamespaceRef(CountryCacheRefMapper.class)
//或者 @CacheNamespaceRef(name = "tk.mybatis.mapper.cache.CountryCacheRefMapper")
public interface CountryCacheRefMapper extends Mapper<Country> {

    /**
     * 定义在 XML 中的方法
     *
     * @param id
     * @return
     */
    Country selectById(Integer id);
}

@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 以及更旧的版本中:

boolean flushCache() default false;

3.4.0+中:

/**
 * The options for the {@link Options#flushCache()}.
 * The default is {@link FlushCachePolicy#DEFAULT}
 */
public enum FlushCachePolicy {
	/** <code>false</code> for select statement; <code>true</code> for insert/update/delete statement. */
	DEFAULT,
	/** Flushes cache regardless of the statement type. */
	TRUE,
	/** Does not flush cache regardless of the statement type. */
	FALSE
}

FlushCachePolicy flushCache() default FlushCachePolicy.DEFAULT;

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