SpringBoot中cache使用的实现示例

 更新时间:2025年10月23日 08:29:50   作者:九丶弟  
本文主要介绍了SpringBoot中cache使用的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

对于SpringBoot的Cache,其实已经有很多文章对使用说明、底层详解等各个角度进行了讲解。
本文则会结合更加详细的使用场景,对cache的存储和查询逻辑进行说明。

缓存的增删改查

查询数据列表

先看一段代码

@Cacheable(value = "devices")
public Set<Integer> getAllDeviceId() {
    LambdaQueryWrapper<DevicePo> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(DevicePo::getIsDelete,false);
    List<DevicePo> devicePos = deviceMapper.selectList(queryWrapper);
    if(CollectionUtils.isEmpty(devicePos)){
        return Collections.emptyList();
    }
    Set<Integer> deviceIds = devicePos.stream().collect(Collectors.toMap(DevicePo::getDeviceId, DevicePo::getDeviceName)).keySet();
    return deviceIds;
}

使用@Cacheable可以读取数据并存储到缓存中,这比较好理解。 在这里value则是代表了一个缓存池(请允许我暂时先这么叫),表示从数据库查询出的数据会保存到名为devices的缓存池中。
在下次调用时,则会先检测缓存池devices中是否有数据,如果有数据,就直接返回,没有数据就执行方法,产生新的数据。

为什么返回的是id集合?而不是数据集合?

在还没有讲到新增和删除缓存数据时,可以理解为,是为了节省内存的占用。
如果缓存的是数据集合,当有一个【根据id获取数据的方法时】就会造成内存中缓存了两份数据,这无疑造成了缓存的浪费。
本质上,你可以理解,在缓存数据集合和单条数据时,其实并没有共用一块数据内存。只是非常关键的一个概念,千万不要误认为数据集合和单条数据共用一块数据内存。

查询单个数据

@Cacheable(value = "devices", key = "#id")
public DevicePo getById(Integer id) {
    if (id == null) {
        return null;
    }
    return deviceMapper.selectById(id);
}

相比于【获取数据集合】,单条数据多了请求参数,在@Cacheable注解中也多了key,虽然value都是devices,如果还是以【缓存池】来代表value的话,表面看【查询所有数据集合方法】和【获取单条数据】的@Cacheable注解value都为devices,好像共用了一个缓存池,而key则会被误认为是从【缓存池】中在数据集合中进行了过滤,这也可能会让人为认为它们的数据地址也是相同的。

其实,共用【缓存池】这么说也没毛病,key作为过滤也没毛病,但最后的结论是错的。

其实springBoot的cache缓存,你可以理解为是两层嵌套的map,即Map<String,Map<String,Object>,map的key1为@Cacheable的value,key2为@Cacheable的key。
那【获取数据集合方法】和【获取单个数据方法】在这个map的存储就变为了:
【获取数据集合方法】: map.get("devices").put("all", list);
【获取单个数据方法】: map.get("devices").put("1", obj); //假设数据id为1

到这里,在新增、修改、删除时,如果你还是一味的只是更新单条数据缓存,就会发现【获取数据集合方法】为什么没有更新了吧。

新增一条新的数据

@CachePut(value = "devices", key = "#result.id")这是一个很标准的新增数据的注解。但是这里面会有两个问题。
首先,可能很多文章会这么写:

@CachePut(value = "devices", key = "#device.id")
public Device add(Device device) {
...
}

这本身没毛病,但是,你的请求参数中有id么? 我猜肯定没有。那我换种写法:

/**
 * @return 返回设备id
 */
@CachePut(value = "devices", key = "#device.id")
public int add(Device device) {
...
}

如果返回的是数据id,或者boolean类型呢?写入缓存的会是什么?还会是数据实体么?肯定不是,并且还会暴露上面那个问题,device中没有id。
那为什么第一种写法没有问题? 你共用一个device实体,在填充id时,请求参数中的id已经被填充了。如果你的请求参数与返回的device不同,这个缓存也就不会保存,因为请求参数的id为null,key为null不会保存到缓存

第二个问题,则是结合上面的查询,如果你也有【获取所有数据集合方法】,那这种写法一定不会更新所有数据集合的缓存。

我们换种写法:

@Caching(evict = {
            @CacheEvict(value = "devices", allEntries = true),
            @CacheEvict(value = "devices", key = "#result")
    })
public int add(Device device) {
...
}

使用@Caching来处理,一个是删除所有数据集合缓存,一个是删除单条数据缓存,单条数据缓存的key则是用返回值(如果你的返回值是实体本身,也可以用put代替)

这样在下次调用查询接口时,就会重新生成缓存。

更新一条数据

逻辑与新增相同,这里就不再赘述

删除一条数据

逻辑与新增相同,这里就不再赘述

到此这篇关于SpringBoot中cache使用的实现示例的文章就介绍到这了,更多相关SpringBoot cache使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot中使用Spring Retry重试框架的操作方法

    Spring Boot中使用Spring Retry重试框架的操作方法

    这篇文章主要介绍了Spring Retry 在SpringBoot 中的应用,介绍了RetryTemplate配置的时候,需要设置的重试策略和退避策略,需要的朋友可以参考下
    2022-04-04
  • java 中volatile和lock原理分析

    java 中volatile和lock原理分析

    这篇文章主要介绍了java 中volatile和lock原理分析的相关资料,需要的朋友可以参考下
    2017-03-03
  • 使用BitSet位集合,一个重复校验工具

    使用BitSet位集合,一个重复校验工具

    这篇文章主要介绍了使用BitSet位集合,一个重复校验工具,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • 详解Java ScheduledThreadPoolExecutor的踩坑与解决方法

    详解Java ScheduledThreadPoolExecutor的踩坑与解决方法

    最近项目上反馈某个重要的定时任务突然不执行了,很头疼,开发环境和测试环境都没有出现过这个问题。定时任务采用的是ScheduledThreadPoolExecutor,后来一看代码发现踩了一个大坑。本文就来和大家聊聊这次的踩坑记录与解决方法,需要的可以参考一下
    2022-10-10
  • Java中Retry方法的简单实现

    Java中Retry方法的简单实现

    这篇文章主要介绍了Java中Retry方法的简单实现,Retry主要是利用Java的lambda表达式和线程接口实现有返回值和无返回值的重试,思考了下就写了一个简易Retry功能分享出来,需要的朋友可以参考下
    2024-01-01
  • Java多态概念、实现机制与实践应用详解

    Java多态概念、实现机制与实践应用详解

    多态是指同一个方法在不同对象上具有不同的行为,通过多态程序可以在运行时决定调用哪个方法,从而提高代码的灵活性和可扩展性,这篇文章主要介绍了Java多态概念、实现机制与实践应用的相关资料,需要的朋友可以参考下
    2026-01-01
  • java使用dom4j生成与解析xml文档的方法示例

    java使用dom4j生成与解析xml文档的方法示例

    这篇文章主要介绍了java使用dom4j生成与解析xml文档的方法,结合实例形式分析了java基于dom4j操作xml节点生成xml文档以及解析xml文档的相关操作技巧,需要的朋友可以参考下
    2017-07-07
  • Java运行时多态性的实现

    Java运行时多态性的实现

    Java运行时多态性的实现...
    2006-12-12
  • vue3实现一个todo-list

    vue3实现一个todo-list

    这篇文章主要为大家详细介绍了基于vuejs实现一个todolist项目,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-08-08
  • Java Selenium实现多窗口切换的示例代码

    Java Selenium实现多窗口切换的示例代码

    这篇文章主要介绍了Java Selenium实现多窗口切换的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09

最新评论