前置
什么是一级缓存: mybatis 默认开启一级缓存, SQLSession会话缓存, 每个SQLSession都会有各自的缓存
以下会演示一级缓存生效/失效的场景
项目地址: https://gitee.com/xmaxm/chaim-code-template/blob/master/chaim-cache/chaim-mybatis-cache/chaim-mybatis-cache-one/README.md
相关缓存文章
Mybatis的一级缓存
Mybatis的二级缓存 (默认方式)
Mybatis的二级缓存 (Redis方式)
Mybatis的二级缓存 (ehcache方式)
生效
场景一
测试一级缓存生效, 默认开启, 需要保证在同一个 SqlSession (可使用 @Transactional 保持其同一个会话)
使用mybatis plus方法
@Transactional
public void queryingLevelCache() {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(SysUser::getUsername, SysUser::getPhone, SysUser::getId);
queryWrapper.last("limit 1");
SysUser sysUsers = sysUserMapper.selectOne(queryWrapper);
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
SysUser user = sysUserMapper.selectOne(queryWrapper);
log.info("查询成功, 观察日志, id: {}", user.getId());
}
场景二
测试一级缓存生效, 默认开启, 需要保证在同一个 SqlSession (可使用 @Transactional 保持其同一个会话)
使用自定义SQL
@Transactional
public void queryingLevelCache(Integer integer) {
SysUser sysUsers = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
SysUser user = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", user.getId());
}
失效
场景一
测试一级缓存失效: 当两次查询存在之间, 存在增删改的情况
public void queryingLevelCacheFail() {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(SysUser::getUsername, SysUser::getPhone, SysUser::getId);
queryWrapper.last("limit 1");
SysUser sysUsers = sysUserMapper.selectOne(queryWrapper);
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
SysUser sysUser = SysUser.builder()
.username("潇潇")
.email("gmail.com")
.phone("000123")
.password("123456")
.sex(1)
.state(0)
.salt(1234)
.build();
sysUserMapper.insert(sysUser);
log.info("观察新增日志, id: {}", sysUsers.getPassword());
SysUser user = sysUserMapper.selectOne(queryWrapper);
log.info("查询成功, 观察日志, id: {}", user.getId());
}
场景二
测试一级缓存失效: 当两次查询的方式不一样, 使用mybatis的方法, 以及自定义SQL
同理, 当查询的条件以及查询的内容不一致时也会失效
public void queryingLevelCacheFail(Integer integer) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(SysUser::getUsername, SysUser::getPhone);
queryWrapper.last("limit 1");
SysUser sysUsers = sysUserMapper.selectOne(queryWrapper);
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
SysUser user = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", user.getId());
}
场景三
测试一级缓存失效: 手动清除缓存
@Override
public void queryingLevelCacheFail(String string) {
SysUser sysUsers = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
sqlSession.clearCache();
SysUser user = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", user.getId());
}
场景四
测试一级缓存失效: 去除@Transactional, 使其不在同一个 SqlSession
@Override
public void queryingLevelCacheFail(Boolean blo) {
SysUser sysUsers = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
SysUser user = sysUserMapper.selectHandwritingSql();
log.info("查询成功, 观察日志, id: {}", user.getId());
}
场景五
测试一级缓存失效:
xml配置: flushCache=“true”
注解方式SQL配置: @Options(flushCache = Options.FlushCachePolicy.TRUE)
同理还可以全局配置: 禁用mybatis一级缓存: mybatis-plus.configuration.local-cache-scope: statement. 默认开始 session
@Override
public void queryingLevelCacheFail(Long lon) {
SysUser sysUsers = sysUserMapper.selectHandwritingSqlFail();
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
SysUser user = sysUserMapper.selectHandwritingSqlFail();
log.info("查询成功, 观察日志, id: {}", user.getId());
log.info("-----------自义定SQL的两种失效方式-----------------");
sysUsers = sysUserMapper.selectHandwritingSqlFail2();
log.info("查询成功, 观察日志, id: {}", sysUsers.getId());
user = sysUserMapper.selectHandwritingSqlFail2();
log.info("查询成功, 观察日志, id: {}", user.getId());
}
<select id="selectHandwritingSqlFail" resultType="com.chaim.mybatis.cache.one.entitys.SysUser" flushCache="true">
SELECT username,phone,id FROM sys_user limit 1
</select>
@Options(flushCache = Options.FlushCachePolicy.TRUE)
@Select("SELECT username,phone,id FROM sys_user limit 1")
SysUser selectHandwritingSqlFail2();