MyBatiesPlus+Redis分布式缓存
一、开启二级缓存
cache-enabled: true
# mybatis-plus相关配置
mybatis-plus:
# xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
mapper-locations: classpath:mapper/*.xml
# 以下配置均有默认值,可以不设置
global-config:
db-config:
#主键类型 AUTO:"数据库ID自增" INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: auto
#字段策略 IGNORED:"忽略判断" NOT_NULL:"非 NULL 判断") NOT_EMPTY:"非空判断"
field-strategy: NOT_EMPTY
#数据库类型
db-type: ORACLE
configuration:
# 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
map-underscore-to-camel-case: true
# 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
call-setters-on-nulls: true
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 一级缓存配置 一级缓存是本地或者说局部缓存,它不能被关闭,只能配置缓存范围。SESSION 或者 STATEMENT。
local-cache-scope: session
# 二级缓存总开关
cache-enabled: true
二、添加缓存注解
@EnableCaching
@SpringBootApplication
@MapperScan({"com.qiang.mybaties.plus.test.cache.dao"})
@EnableCaching
public class MybatiesPlusCacheApplication {
public static void main(String[] args) {
SpringApplication.run(MybatiesPlusCacheApplication.class, args);
}
}
三、实体类实现接口
Serializable
@Data
public class Account extends Model implements Serializable{
private Integer id;
private Integer balance;
private Integer freezeMoney;
/**
* 获取主键值
*
* @return 主键值
*/
@Override
protected Serializable pkVal() {
return this.id;
}
}
四、配置Redis模板
RedisConfig
@Configuration
public class RedisConfig {
/**
* 配置RedisTemplate
*
* @param factory
* @return
*/
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory, Jackson2JsonRedisSerializer serializer) {
RedisTemplate
五、配置Redis缓存
RedisCache
public final class RedisCache implements Cache {
/**
* 日志
*/
private static final Logger logger = LogManager.getLogger(RedisCache.class);
/**
* 读写锁
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* ID,获取缓存对象的唯一标识
*/
private String id;
/**
* redisTemplate
*/
private static RedisTemplate redisTemplate;
public RedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("缓存实例需要一个id!");
} else {
logger.info("开启Redis缓存: id = {}", id);
this.id = id;
}
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
try {
if (redisTemplate == null) {
redisTemplate = getRedisTemplate();
}
Long size = redisTemplate.opsForHash().size(this.id.toString());
logger.info("Redis缓存大小: id = {}, size = {}", id, size);
return size.intValue();
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
@Override
public void putObject(final Object key, final Object value) {
try {
if (redisTemplate == null) {
redisTemplate = getRedisTemplate();
}
logger.info("设置Redis缓存: id = {}, key = {}, value = {}", id, key, value);
redisTemplate.opsForHash().put(this.id.toString(), key.toString(), value);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getObject(final Object key) {
try {
if (redisTemplate == null) {
redisTemplate = getRedisTemplate();
}
Object hashVal = redisTemplate.opsForHash().get(this.id.toString(), key.toString());
logger.info("获取Redis缓存: id = {}, key = {}, hashVal = {}", id, key, hashVal);
return hashVal;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public Object removeObject(final Object key) {
try {
if (redisTemplate == null) {
redisTemplate = getRedisTemplate();
}
redisTemplate.opsForHash().delete(this.id.toString(), key.toString());
logger.info("移除Redis缓存: id = {}, key = {}", id, key);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void clear() {
try {
if (redisTemplate == null) {
redisTemplate = getRedisTemplate();
}
redisTemplate.delete(this.id.toString());
logger.info("清空Redis缓存: id = {}", id);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
@Override
public String toString() {
return "RedisCache {" + this.id + "}";
}
/**
* 由于启动期间注入失败,只能运行期间注入
*
* @return
*/
public RedisTemplate getRedisTemplate() {
redisTemplate = (RedisTemplate) SpringUtil.getBean("redisTemplate");
return redisTemplate;
}
}
SpringUtil
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtil.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static T getBean(String name, Class clazz) {
return applicationContext.getBean(name, clazz);
}
public static T getBean(Class clazz) {
return applicationContext.getBean(clazz);
}
}
六、在Dao层使用
AccountDao,此时,MybatiesPlus自带的方法缓存已经生效。但是Xml文件里的方法还未生效,接着下一步
// 使用缓存
@CacheNamespace(implementation= RedisCache.class,eviction=RedisCache.class)
public interface AccountDao extends BaseMapper {
/**
* 查询去重的Balance
* @return
*/
List selectDistinctBalance();
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
Account queryById(Integer id);
/**
* 查询指定行数据
*
* @param offset 查询起始位置
* @param limit 查询条数
* @return 对象列表
*/
List queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit);
/**
* 通过实体作为筛选条件查询
*
* @param account 实例对象
* @return 对象列表
*/
List queryAll(Account account);
/**
* 新增数据
*
* @param account 实例对象
* @return 影响行数
*/
int insertOne(Account account);
/**
* 修改数据
*
* @param account 实例对象
* @return 影响行数
*/
int update(Account account);
/**
* 通过主键删除数据
*
* @param id 主键
* @return 影响行数
*/
int deleteById(Integer id);
}
七、在Xml文件使用
AccountDao.xml
<?xml version="1.0" encoding="UTF-8"?>
ID, BALANCE, FREEZE_MONEY
insert into TEST.ACCOUNT(BALANCE, FREEZE_MONEY)
values (#{balance}, #{freezeMoney})
update TEST.ACCOUNT
BALANCE = #{balance},
FREEZE_MONEY = #{freezeMoney},
where ID = #{id}
delete from TEST.ACCOUNT where ID = #{id}
八、验证是否成功
8.1 作用域为自带方法
测试代码
@Test
public void testRedisCacheCommon(){
// 测试 mybaties-plus 中间件为redis 作用域为 mybaties自带方法 的二级缓存
List list1 = accountService.list();
System.out.println(list1);
List list2 = accountService.list();
System.out.println(list2);
}
结果看到第二次查询使用了缓存

Redis也成功添加缓存

缓存更新
@Test
public void testRedisCacheCommon(){
// 测试 mybaties-plus 中间件为redis 作用域为 mybaties自带方法 的二级缓存
List list1 = accountService.list();
System.out.println(list1);
boolean b = accountService.removeById(2);
System.out.println(b);
List list2 = accountService.list();
System.out.println(list2);
}
结果看到查询了两次数据库,当缓存作用在同一个CacheNamespace时候,发生增删改操作,则缓存更新

8.2 作用域为Xml文件
测试代码
@Test
public void testRedisCacheByXml() {
// 测试 mybaties-plus 中间件为redis 作用域为 xml文件 的二级缓存
Account account = new Account();
account.setId(1);
List accounts1 = accountService.queryAll(account);
System.out.println(accounts1);
List accounts2 = accountService.queryAll(account);
System.out.println(accounts2);
}
结果看到第二次查询使用了缓存

Redis也成功添加缓存

缓存更新
@Test
public void testRedisCacheByXml() {
// 测试 mybaties-plus 中间件为redis 作用域为 xml文件 的二级缓存
Account account = new Account();
account.setId(1);
List accounts1 = accountService.queryAll(account);
System.out.println(accounts1);
int i = accountService.deleteById(1);
System.out.println(i);
List accounts2 = accountService.queryAll(account);
System.out.println(accounts2);
}
结果看到查询了两次数据库,当缓存作用在同一个CacheNamespace时候,发生增删改操作,则缓存更新

作者(Author):小强崽
来源(Source):https://www.wuduoqiang.com/archives/MyBatiesPlus+Redis分布式缓存
协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
版权(Copyright):商业转载请联系作者获得授权,非商业转载请注明出处。 For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.