Spring boot redis cache的key的使用方法

 更新时间:2019年05月12日 15:31:37   作者:Simeone_xu  
这篇文章主要介绍了Spring boot redis cache的key的使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在数据库查询中我们往往会使用增加缓存来提高程序的性能,@Cacheable 可以方便的对数据库查询方法加缓存。本文主要来探究一下缓存使用的key。

搭建项目

数据库

mysql> select * from t_student;
+----+--------+-------------+
| id | name  | grade_class |
+----+--------+-------------+
| 1 | Simone | 3-2     |
+----+--------+-------------+
1 row in set (0.01 sec)

spring boot 配置

#jpa
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/pratice
spring.datasource.username=root
spring.datasource.password=123456
#redis
spring.redis.host=localhost
spring.redis.lettuce.pool.maxActive=5
spring.redis.lettuce.pool.maxIdle=5
#cache
spring.cache.cache-names=Cache
spring.cache.redis.time-to-live=300000

数据访问层

public interface StudentDao extends CrudRepository<Student, Long> {

  @Cacheable(value = "Cache")
  @Override
  Optional<Student> findById(Long aLong);

  @Cacheable(value = "Cache")
  Optional<Student> findByName(String name);
}

启动调用数据访问层方法观察

@Override
public void run(ApplicationArguments args) throws Exception {
 Optional<Student> optional = studentDao.findById(1L);
 System.out.println(optional);
}

当默认使用 @Cacheable(value = "Cache") 的时候查看 redis 中缓存的 key

127.0.0.1:6379> keys *
1) "Cache::1"

可以知道 key是由缓存的名字和参数值生成的,key 的生成和方法的名字无关,如果两个方法的参数相同了,就会命中同一个缓存,这样显然是不行的。使用相同的参数调用 findById 和 findByName 观察查询结果

@Override
public void run(ApplicationArguments args) throws Exception {
 Optional<Student> optional = studentDao.findById(1L);
 System.out.println(optional);

 Optional<Student> optionalByName = studentDao.findByName("1");
 System.out.println(optionalByName);
}
//输出结果
//Optional[Student(id=1, name=Simone, gradeClass=3-2)]
//Optional[Student(id=1, name=Simone, gradeClass=3-2)]

从数据库的数据看 studentDao.findByName("1") 应该是查询出空的,但是取命中了缓存,所以我们需要给缓存的 key 加上方法的名字。

@Cacheable(value = "Cache", key = "{#root.methodName, #aLong}")
@Override
Optional<Student> findById(Long aLong);

@Cacheable(value = "Cache", key = "{#root.methodName, #name}")
Optional<Student> findByName(String name);

//Optional[Student(id=1, name=Simone, gradeClass=3-2)] 
//Optional.empty

Redis 中的 Key 也有了方法的名字

127.0.0.1:6379> keys *
1) "Cache::findById,1"
2) "Cache::findByName,1"

在实际项目中我们肯定不是只有一张表,如果其他表使用缓存的名字也是 Cache,很有可能产生相同的 key,比如我还有一个如下的 dao

public interface TeacherDao extends CrudRepository<Teacher, Long> {

  @Cacheable(value = "Cache", key = "{#root.methodName, #aLong}")
  @Override
  Optional<Teacher> findById(Long aLong);

  @Cacheable(value = "Cache", key = "{#root.methodName, #name}")
  Optional<Teacher> findByName(String name);
}

如果在调用 TeacherDao 中的方法命中了 StudentDao 中的方法会产生 ClassCastException ,这里就两种方式来解决这个问题。第一种办法是每个 dao 中都使用不同的缓存名字。第二是给 key 加上类的名字。

我 google 了一下,没有找到使用 Spel 或取到类名的方法(或许有),所以这里通过配置 @Cacheable 的 key参数就不行了。那就只能实现自定义的生成器。

@Bean("customKeyGenerator")
public KeyGenerator keyGenerator() {
 return new KeyGenerator() {
  @Override
  public Object generate(Object o, Method method, Object... objects) {
   return method.getDeclaringClass().getName() + "_"
    + method.getName() + "_"
    + StringUtils.arrayToDelimitedString(objects, "_");
  }
 };
}

设置 @Cacheable 的 keyGenerator 参数

@Cacheable(value = "Cache", keyGenerator = "customKeyGenerator")
@Override
Optional<Student> findById(Long aLong);

@Cacheable(value = "Cache", keyGenerator = "customKeyGenerator")
Optional<Student> findByName(String name);

查看 Redis 中的 key

127.0.0.1:6379> keys *
1) "Cache::me.action.dao.StudentDao_findById_1"
2) "Cache::me.action.dao.StudentDao_findByName_1"

Key 由缓存名、类名、方法名和参数构成,这样足够保险了。在实际开发中可以根据实际情况构造 key 满足需求。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot实现EMQ设备的上下线告警

    SpringBoot实现EMQ设备的上下线告警

    EMQX 的上下线系统消息通知功能在客户端连接成功或者客户端断开连接,需要实现设备的上下线状态监控,所以本文给大家介绍了如何通过SpringBoot实现EMQ设备的上下线告警,文中有详细的代码示例,需要的朋友可以参考下
    2023-10-10
  • mybatis自定义类型处理器TypehHandler示例详解

    mybatis自定义类型处理器TypehHandler示例详解

    我们在写mapper映射器的配置文件时,不经意间已经用到类型转换,不过是mybatis帮我们完成的,下面这篇文章主要给大家介绍了关于mybatis自定义类型处理器TypehHandler的相关资料,需要的朋友可以参考下
    2018-09-09
  • 基于SpringBoot 使用 Flink 收发Kafka消息的示例详解

    基于SpringBoot 使用 Flink 收发Kafka消息的示例详解

    这篇文章主要介绍了基于SpringBoot 使用 Flink 收发Kafka消息,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • @RequestParam注解加与不加有什么区别

    @RequestParam注解加与不加有什么区别

    这篇文章主要介绍了@RequestParam注解加与不加有什么区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • 关于logback.xml和logback-spring.xml的区别及说明

    关于logback.xml和logback-spring.xml的区别及说明

    这篇文章主要介绍了关于logback.xml和logback-spring.xml的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • java:try...catch跳过异常继续处理循环问题

    java:try...catch跳过异常继续处理循环问题

    这篇文章主要介绍了java:try...catch跳过异常继续处理循环问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • SpringBoot+Redis实现查找附近用户的示例代码

    SpringBoot+Redis实现查找附近用户的示例代码

    SpringDataRedis提供了十分简单的地理位置定位的功能,本文主要介绍了SpringBoot+Redis实现查找附近用户的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • springboot加载命令行参数ApplicationArguments的实现

    springboot加载命令行参数ApplicationArguments的实现

    本文主要介绍了springboot加载命令行参数ApplicationArguments的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 高级数据结构及应用之使用bitmap进行字符串去重的方法实例

    高级数据结构及应用之使用bitmap进行字符串去重的方法实例

    今天小编就为大家分享一篇关于高级数据结构及应用之使用bitmap进行字符串去重的方法实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • 关于Maven如何构建生命周期

    关于Maven如何构建生命周期

    这篇文章主要介绍了关于Maven如何构建生命周期,Maven构建生命周期描述的是一次构建过程经历经历了多少个事件,需要的朋友可以参考下
    2023-04-04

最新评论