Clay

用进废退 | 工字不出头

  • 主页
  • 归档
  • 随笔
  • 搜索
所有文章

Clay

用进废退 | 工字不出头

  • 主页
  • 归档
  • 随笔

MyBatis使用J2Cache作为二级缓存实现

发表于:2019-07-21
字数统计:1.7k
阅读量统计:
  • J2Cache 的 Gradle 配置
  • MyBatis 的 Mapper 使用 J2Cache
  • 二级缓存的坑
    • MyBatis-Plus 二级缓存不生效
    • MyBatis 二级缓存不生效
    • 二级缓存配置总结
  • 指定 J2Cache 的缓存大小与有效时间
  • 基于 SpringBoot 的单元测试类
  • J2Cache 的配置文件
  • 临时关闭 MyBatis 使用 J2Cache

J2Cache 的 Gradle 配置

项目中引入以下依赖后,需要根据项目具体的运行状况调整 Gradle 的依赖配置,以下配置使用到 SpringBoot。

1
2
3
compile 'net.oschina.j2cache:j2cache-core:2.7.6-release'
compile 'net.oschina.j2cache:j2cache-mybatis:2.7.0-release'
compile 'net.oschina.j2cache:j2cache-spring-boot2-starter:2.7.6-release'

MyBatis 的 Mapper 使用 J2Cache

首先在 MyBatis 的全局配置中开启二级缓存,然后根据下面的两种情况进行配置(二选一)

1
2
3
4
<settings>
<!-- 开启二级缓存,默认true -->
<setting name="cacheEnabled" value="true"/>
</settings>

第一种使用情况:对当前 namespace 内的所有 sql 启用二级缓存

1
2
3
4
<mapper namespace="com.example.dao.user.UserApiMapper">
<!-- 指定MyBatis的二级缓存实现类 -->
<cache type="net.oschina.j2cache.mybatis.J2CacheAdapter"/>
</mapper>

或者使用 Java 注解进行配置,此写法会导致 XML 映射文件中的其他 SQL 无法使用二级缓存,下面会详细介绍

1
2
3
4
@CacheNamespace(implementation = J2CacheAdapter.class)
public interface UserApiMapper extends BaseMapper<UserApi> {

}

第二种使用情况:对当前 namespace 内指定的 sql 设置是否启用二级缓存

1
2
3
4
5
6
7
8
9
10
<mapper namespace="com.example.dao.user.UserApiMapper">
<!-- 指定MyBatis的二级缓存实现类 -->
<cache type="net.oschina.j2cache.mybatis.J2CacheAdapter"/>

<!-- 通过配置useCache属性,指定当前sql是否启用二级缓存,默认为true,如果设置为false,则每次都会发sql去数据库查询 -->
<select id="selectRecord" resultMap="userApiMap" useCache="false">
select * from man_user_api
where userid = #{userId} and exchange_id = #{exchangeId}
</select>
</mapper>

或者使用 Java 注解进行配置,此写法会导致 XML 映射文件中的其他 SQL 无法使用二级缓存,下面会详细介绍

1
2
3
4
5
6
7
8
@CacheNamespace(implementation = J2CacheAdapter.class)
public interface UserApiMapper extends BaseMapper<UserApi> {

@Options(useCache = false)
@Select("select * from man_user_api where userid = #{userId} and exchange_id = #{exchangeId}")
public UserApi selectRecord(@Param(("userId")) long userId, @Param("exchangeId") long exchangeId);

}

二级缓存的坑

MyBatis-Plus 二级缓存不生效

官方推荐的方式是统一在 XML 映射文件中配置缓存与 SQL,此方式在 MyBatis + MyBatis-Plus(version <= 2.0.9)的环境下可以正常工作。但是当使用版本号大于 2.0.9 的 MyBatis-Plus,使用 XML 配置缓存的方式会导致 MyBatis-Plus 的二级缓存不生效,具体表现为发出的SQL(由 MyBatis-Plus 自动生成的 SQL)不能正常使用二级缓存。根据 MyBatis-Plus 官方文档的说明,当使用 2.0.9 以上的版本,需要在代码中 MyBatis 的 Mapper 层添加缓存注释,声明 implementation 的值为 cache 接口的实现类,此时 XML 映射文件中不能再声明 cache 标签,代码如下:

1
2
3
4
@CacheNamespace(implementation = J2CacheAdapter.class)
public interface UserApiMapper extends BaseMapper<UserApi> {

}
MyBatis 二级缓存不生效

使用 @CacheNamespace 注解后,MyBatis-Plus 的二级缓存确实是生效了,但在 XML 映射文件中的其他 SQL 此时不能正常使用二级缓存,而在 Mapper 层通过注解声明的 SQL 则不受影响。

二级缓存配置总结

不管通过注解还是 XML 的方式配置缓存,总结大概有以下几种使用情况。实际开发中可以根据不同的业务需求混合使用不同的配置方式,第一种方式适合 SQL 比较复杂的业务场景,第三种方式适合 SQL 比较简单的业务场景,推荐第一种方式。

  • 第一种:MyBatis 单独正常使用二级缓存,将所有 SQL、缓存配置都写在 XML 映射文件中,此时 MyBatis-Plus 的二级缓存失效;
  • 第二种:MyBatis-Plus 正常使用二级缓存,在 Mapper 层声明注解 @CacheNamespace,此时 MyBatis 的二级缓存失效(针对 XML 中定义的 SQL),而 MyBatis 通过 Java注解定义的 SQL 则依然会生效;
  • 第三种:MyBatis 与 MyBatis-Plus 同时正常使用二级缓存,将所有 SQL、缓存配置通过注解的方式定义在 Mapper 层;此时 XML 映射文件中不能再定义 SQL,否则 XML 中的 SQL 无法使用二级缓存。

指定 J2Cache 的缓存大小与有效时间

当 J2Cache 作为 MyBatis 的二级缓存实现,J2Cache 官方支持在配置文件中指定缓存的大小与有效时间,具体配置如下:

1
2
3
4
5
6
7
8
9
10
# redis storage mode (generic|hash)
lettuce.storage = generic

# Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)
# NOTICE: redis hash mode (redis.storage = hash) do not support this feature)
j2cache.sync_ttl_to_redis = true

# ttl for one level cache
# [name] = size, xxxx[s|m|h|d]
caffeine.region.default = 1000, 30m

重点关注的配置是 “caffeine.region.default”,上面配置了默认 Region(区域)的一级缓存大小为1000,有效时间为 30 分钟。举个例子,如果需要为 UserAPI 表的记录单独设置缓存大小和有效时间,可以参考以下配置;其中 Region 是 Mapper 的类全名,大小为 2000,有效时间为 12 小时。当 J2Cache 找不到对应的 Region,默认会采用 “caffeine.region.default” 的配置策略。

1
caffeine.region.com.example.dao.user.UserApiMapper = 2000, 12h

基于 SpringBoot 的单元测试类

当 MyBatis 的 Mapper 使用 J2Cache 作为二级缓存的实现,那么单元测试类中暂时需要指定 J2Cache 的相关配置,否则测试类无法正常启动。如果每个测试类都要加上一堆 J2Cache 的配置内容,实在是不方便,而且 J2Cache 的配置一旦更改,则需要修改每个测试类的代码。为了解决这种情况,可以在模块下创建 BaseSpringBootTest 基础测试类,然后其他测试类直接继承基础测试类即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* 基础测试类
*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {
"j2cache.l2-cache-open=true",
"j2cache.open-spring-cache=true",
"j2cache.allow-null-values=true",
"spring.cache.type=GENERIC",
"j2cache.cache-clean-mode=passive",
"j2cache.config-location=classpath:j2cache.properties"})
public class BaseSpringBootTest {

protected Logger logger = LoggerFactory.getLogger(BaseSpringBootTest.class);

}

/**
* 具体的测试类实现
*/
public class J2CacheMyBatisTest extends BaseSpringBootTest {

@Autowired
private UserApiMapper apiMapper;

private Logger logger = LoggerFactory.getLogger(J2CacheMyBatisTest.class);

@Test
public void util() {
UserApi api = apiMapper.selectById(1L);
logger.info("===> " + api);
}
}

J2Cache 的配置文件

J2Cache 支持使用 Redis 或者 RabbitMQ 的 Pub/Sub 服务,支持使用 Ehcache、Caffeine 作为一级缓存,支持使用 Jedis、Lettuce 作为 Redis 的客户端。目前 J2Cache 最主要的配置内容只能写在 j2cache.properties 文件中,如果将配置内容全部移动到 SpringBoot 的 xxx.yml 文件中,SpringBoot 应用的启动与单元测试都会出错,这与 J2Cache 的源码有关。

临时关闭 MyBatis 使用 J2Cache

在 MyBatis 的全局配置中,关闭二级缓存即可。

1
2
3
4
<settings>
<!-- 关闭二级缓存,默认true -->
<setting name="cacheEnabled" value="false"/>
</settings>
本文作者: Clay
发布时间: 2019-07-21 19:18:21
本文链接: https://www.techgrow.cn/posts/ee90f3ef.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
赏

谢谢你的支持

支付宝
微信
  • Java
  • 缓存

扫一扫,分享到微信

微信分享二维码
分布式技术面试题之一
Linux破解安装XMind8
© 2021 Clay
本站总访问量  人次
载入天数...载入时分秒...
粤ICP备19024664号
  • 所有文章

显示标签:

  • AI
  • C/C++
  • CI/CD
  • CentOS
  • Centos
  • Docker
  • HarmonyOS
  • Java
  • Linux
  • Manjaro
  • Python
  • Web服务器
  • 企业面试
  • 分布式
  • 前端
  • 区块链
  • 开发工具
  • 开源
  • 微服务
  • 数据库
  • 架构
  • 树莓派
  • 爬虫
  • 版本控制
  • 知识图谱
  • 算法与数据结构
  • 缓存
  • 网络攻防
  • 随笔

    [^_^] 出错啦!请重新刷新页面!