详解如何使用SpringBoot的缓存@Cacheable

 更新时间:2023年06月27日 11:28:40   作者:小石读史  
这篇文章主要为大家介绍了如何使用SpringBoot的缓存@Cacheable详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

缓存介绍

Spring 从 3.1 开始就引入了对 Cache 的支持。定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术。并支持使用 JCache(JSR-107)注解简化我们的开发。

其使用方法和原理都类似于 Spring 对事务管理的支持。Spring Cache 是作用在方法上的,其核心思想是,当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存在缓存中。

Cache 和 CacheManager 接口说明

Cache 接口包含缓存的各种操作集合,你操作缓存就是通过这个接口来操作的。

Cache 接口下 Spring 提供了各种 xxxCache 的实现,比如:RedisCache、EhCache、ConcurrentMapCache

CacheManager 定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文中。

小结:

每次调用需要缓存功能的方法时,Spring 会检查指定参数的指定目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。

二、@Cacheable 注解使用详细介绍

@Cacheable 这个注解,用它就是为了使用缓存的。所以我们可以先说一下缓存的使用步骤:

缓存使用步骤

1、开启基于注解的缓存,使用 @EnableCaching 标识在 SpringBoot 的主启动类上。

2、标注缓存注解即可

① 第一步:开启基于注解的缓存,使用 @EnableCaching 标注在 springboot 主启动类上

@EnableSwagger2
@EnableScheduling
@EnableFeignClients(basePackages = {"src.main.biz.smallProject.client","com.codingapi.tx"})
@EnableJpaRepositories(basePackages = {"src.main.biz.smallProject.web.*.dao","src.main.newgrand.framework.common.dao" })
@EntityScan(basePackages = { "src.main.biz.smallProject.web.*.entity","src.main.newgrand.framework.common.domain"})
@EnableCaching
public class StartApp {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(StartApp.class);
        new SpringUtil().setApplicationContext(context);
    }
}

② 第二步:标注缓存注解

package src.main.biz.smallProject.web.cost.service.impl;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import src.main.biz.smallProject.utils.CollectionUtils;
import src.main.biz.smallProject.web.construct.form.IdsForm;
import src.main.biz.smallProject.web.cost.dao.BusinessScopeJPA;
import src.main.biz.smallProject.web.cost.entity.BusinessScopeEntity;
import src.main.biz.smallProject.web.cost.entity.QBusinessScopeEntity;
import src.main.biz.smallProject.web.cost.form.BusinessScopeForm;
import src.main.biz.smallProject.web.cost.form.BusinessScopeQueryForm;
import src.main.biz.smallProject.web.cost.service.BusinessScopeService;
import src.main.biz.smallProject.web.cost.vo.BusinessScopeVO;
import src.main.newgrand.framework.common.constants.PageData;
import src.main.newgrand.framework.common.exception.BusinessException;
import src.main.newgrand.framework.common.service.impl.BaseServiceImpl;
import src.main.newgrand.framework.common.utils.ResultRes;
import java.time.LocalDateTime;
import java.util.List;
import static src.main.biz.smallProject.redis.CacheConstants.BUSINESS_SCOPE_CACHE;
/**
 * @Description
 * @Author    yql
 * @Date 2022-05-10 10:44:29 */
@Service
public class BusinessScopeServiceImpl extends BaseServiceImpl<BusinessScopeJPA, BusinessScopeEntity, BusinessScopeVO> implements BusinessScopeService {
    @Autowired
    private JPAQueryFactory jpaQueryFactory;
    QBusinessScopeEntity qBusinessScopeEntity = QBusinessScopeEntity.businessScopeEntity;
    @Autowired
    private BusinessScopeService businessScopeService;
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    @CacheEvict(cacheNames = {BUSINESS_SCOPE_CACHE}, allEntries = true)
    public ResultRes add(BusinessScopeForm form) {
        BusinessScopeEntity businessScopeEntity = new BusinessScopeEntity();
        BeanUtils.copyProperties(form,businessScopeEntity);
        businessScopeService.save(businessScopeEntity);
        return ResultRes.success();
    }
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    @CacheEvict(cacheNames = {BUSINESS_SCOPE_CACHE}, allEntries = true)
    public ResultRes update(BusinessScopeForm form) {
        BusinessScopeEntity businessScopeEntity = findById(form.getPhid());
        if(businessScopeEntity == null){
            throw new BusinessException("数据不存在,请检查!");
        }
        BeanUtils.copyProperties(form,businessScopeEntity);
        businessScopeService.updateSelectiveById(businessScopeEntity);
        return ResultRes.success();
    }
    @Override
    @Cacheable(cacheNames = BUSINESS_SCOPE_CACHE, key = "{ " + "#root.methodName, #form.status}", unless = "#result == null")
    public ResultRes<PageData> list(BusinessScopeQueryForm form) {
        long currPage = form.getCurrent();
        long size = form.getSize();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qBusinessScopeEntity.phDelflag.eq(0L));
        if(form.getStatus() != null){
            booleanBuilder.and(qBusinessScopeEntity.status.eq(form.getStatus()));
        }
        QueryResults<BusinessScopeVO> results = jpaQueryFactory
                .select(Projections.bean(
                        BusinessScopeVO.class,
                        qBusinessScopeEntity.phid,
                        qBusinessScopeEntity.name,
                        qBusinessScopeEntity.status))
                .from(qBusinessScopeEntity)
                .where(booleanBuilder)
                .orderBy(qBusinessScopeEntity.phInsertDt.desc())
                .offset((currPage - 1) * size)
                .limit(size).fetchResults();
        PageData pageData = new PageData(results.getResults(), results.getTotal(), size, currPage);
        return ResultRes.success(pageData);
    }
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    @CacheEvict(cacheNames = {BUSINESS_SCOPE_CACHE}, allEntries = true)
    public ResultRes deleteData(IdsForm form) {
        List<Long> ids = form.getIds();
        List<BusinessScopeEntity> businessScopeEntityList = queryFactory.selectFrom(qBusinessScopeEntity)
                .where(qBusinessScopeEntity.phid.in(ids).and(qBusinessScopeEntity.phDelflag.eq(0L)))
                .fetch();
        if(CollectionUtils.isEmpty(businessScopeEntityList)){
            throw new BusinessException("数据不存在,请检查!");
        }
        queryFactory.update(qBusinessScopeEntity)
                .set(qBusinessScopeEntity.phDelflag, 1L)
                .set(qBusinessScopeEntity.phUpdateDt, LocalDateTime.now())
                .where(qBusinessScopeEntity.phid.in(ids))
                .execute();
        return ResultRes.success();
    }
}

常用属性说明

cacheNames/value :用来指定缓存组件的名字

key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)

keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用

cacheManager :可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。

condition :可以用来指定符合条件的情况下才缓存

unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)

sync :是否使用异步模式。

spEL 编写 key

前面说过,缓存的 key 支持使用 spEL 表达式去编写,下面总结一下使用 spEL 去编写 key 可以用的一些元数据:

以上就是详解如何使用SpringBoot的缓存@Cacheable的详细内容,更多关于SpringBoot缓存@Cacheable的资料请关注脚本之家其它相关文章!

相关文章

  • 浅谈十个常见的Java异常出现原因

    浅谈十个常见的Java异常出现原因

    这篇文章主要介绍了十个常见的Java异常出现原因,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Spring MVC温故而知新系列教程之请求映射RequestMapping注解

    Spring MVC温故而知新系列教程之请求映射RequestMapping注解

    这篇文章主要介绍了Spring MVC温故而知新系列教程之请求映射RequestMapping注解的相关知识,文中给大家介绍了RequestMapping注解提供的几个属性及注解说明,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-05-05
  • JAVA中的延迟队列DelayQueue应用解析

    JAVA中的延迟队列DelayQueue应用解析

    这篇文章主要介绍了JAVA中的延迟队列DelayQueue应用解析,DelayQueue是一个根据元素的到期时间来排序的队列,而并非是一般的队列那样先进先出,最快过期的元素排在队首,越晚到期的元素排得越后,需要的朋友可以参考下
    2023-12-12
  • java实现静默加载Class示例代码

    java实现静默加载Class示例代码

    这篇文章主要给大家介绍了关于java实现静默加载Class的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-10-10
  • springboot结合maven配置不同环境的profile方式

    springboot结合maven配置不同环境的profile方式

    这篇文章主要介绍了springboot结合maven配置不同环境的profile方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • java分布式事务seata的使用方式

    java分布式事务seata的使用方式

    这篇文章主要介绍了java分布式事务seata的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • SpringBoot解析JSON数据的三种方案

    SpringBoot解析JSON数据的三种方案

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,本文给大家介绍了SpringBoot解析JSON数据的三种方案,需要的朋友可以参考下
    2024-03-03
  • 详解Java构建树结构的公共方法

    详解Java构建树结构的公共方法

    本文主要介绍了详解Java构建树结构的公共方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Spring Bean属性注入的两种方式详解

    Spring Bean属性注入的两种方式详解

    Spring 属性注入(DI依赖注入)有两种方式:setter注入,构造器注入。本文将详细为大家介绍一下这两种方式的具体用法,感兴趣的可以了解一下
    2022-06-06
  • Java数组的声明与创建示例详解

    Java数组的声明与创建示例详解

    这篇文章主要介绍了Java数组的声明与创建示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07

最新评论