当前位置: 首页 > 知识库问答 >
问题:

在应用程序启动时缓存查找不起作用

闽阳州
2023-03-14

我在Tomcat 9.0.2上使用Spring Boot 1.5.9,并且我尝试使用Spring@Cacheable调度缓存刷新作业,该作业在应用程序启动时运行并每24小时重复一次,如下所示:

@Component
public class RefreshCacheJob {

    private static final Logger logger = LoggerFactory.getLogger(RefreshCacheJob.class);

    @Autowired
    private CacheService cacheService;

    @Scheduled(fixedRate = 3600000 * 24, initialDelay = 0)
    public void refreshCache() {
        try {
            cacheService.refreshAllCaches();
        } catch (Exception e) {
            logger.error("Exception in RefreshCacheJob", e);
        }
    }

}

缓存服务如下:

@Service
public class CacheService {

    private static final Logger logger = LoggerFactory.getLogger(CacheService.class);

    @Autowired
    private CouponTypeRepository couponTypeRepository;

    @CacheEvict(cacheNames = Constants.CACHE_NAME_COUPONS_TYPES, allEntries = true)
    public void clearCouponsTypesCache() {}

    public void refreshAllCaches() {
        clearCouponsTypesCache();
        List<CouponType> couponTypeList = couponTypeRepository.getCoupons();
        logger.info("######### couponTypeList: " + couponTypeList.size());
    }
}

存储库代码:

public interface CouponTypeRepository extends JpaRepository<CouponType, BigInteger> {
    @Query("from CouponType where active=true and expiryDate > CURRENT_DATE order by priority")
    @Cacheable(cacheNames = Constants.CACHE_NAME_COUPONS_TYPES)
    List<CouponType> getCoupons();
}

稍后在我的webservice中,当尝试获取查找时,如下所示:

@GET
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
@Path("/getCoupons")
@ApiOperation(value = "")
public ServiceResponse getCoupons(@HeaderParam("token") String token, @HeaderParam("lang") String lang) throws Exception {
    try {
        List<CouponType> couponsList = couponRepository.getCoupons();
        logger.info("###### couponsList: " + couponsList.size());
        return new ServiceResponse(ErrorCodeEnum.SUCCESS_CODE, resultList, errorCodeRepository, lang);
    } catch (Exception e) {
        logger.error("Exception in getCoupons webservice: ", e);
        return new ServiceResponse(ErrorCodeEnum.SYSTEM_ERROR_CODE, errorCodeRepository, lang);
    }
}

第一次调用它从数据库中获取查找,后续调用它从缓存中获取,而它应该在web服务的第一次调用中从缓存中获取?

为什么我会有这种行为,我该如何解决?

共有3个答案

严兴言
2023-03-14

@CacheEvict在同一服务内调用时不会被调用。这是因为Spring围绕服务创建了一个代理,只有来自“外部”的调用才会通过缓存代理。

解决方案是添加

@CacheEvict(cacheNames=Constants.CACHE\u NAME\u coups\u TYPES,allEntries=true)

也可以将refreshAllCaches移动到调用ICacheService的新服务中。clearCouponsTypeCache。

李康安
2023-03-14

虽然它本身不影响计划任务,但当在CacheService中调用刷新AllCache()时,clearCouponsTypes Cache()上的@CacheEvict被绕过,因为它是从同一个类调用的(参见此答案)。这将导致缓存之前不被清除

List<CouponType> couponTypeList = couponTypeRepository.getCoupons();

被调用。这意味着Cacheable方法不会查询数据库,而是从缓存返回值。

这使得计划的缓存刷新操作仅在缓存为空时正常工作一次。之后就没用了。

@CacheEvict注解应该移动到刷新AllCache()方法并向其添加beforeInvdge=true参数,因此缓存在填充之前被清除,而不是之后。

此外,当使用Spring4/Spring护套1时。十、 应考虑这些缺陷:

  • https://github.com/spring-projects/spring-boot/issues/8331

虽然这个bug似乎不会影响这个特定的程序,但在迁移到Spring 5/Spring Boot 2之前,最好将可缓存的注释从JpaRepository接口中分离出来。十、

师俊健
2023-03-14

该问题在升级到Tomcat 9.0.4后得到修复

 类似资料:
  • 在应用程序(Spring引导服务)启动时,需要清除Redis缓存。 Redis运行在另一个docker容器中,该容器具有自己的卷映射。因为它保留了旧的缓存,所以即使在应用程序重新启动后,应用程序也会从Redis缓存而不是数据库中拾取数据 > 尝试了的,但它从未被调用。 在Application ationMain类中尝试了,但是它没有清除缓存。 尝试使用,但仍然没有运气 @组件公共类应用程序启动{

  • 我有一份Java申请。 应用程序有一个决定应用程序是否在启动时启动的设置。 目前,我通过在StartUp items文件夹中放置/删除快捷方式实现了这一点。 然而,我想知道是否有更好的方法来处理这种行为。 编辑 是的,是视窗。抱歉之前没有清除。 应用程序有一个UI,用户可以在其中触发操作,并且应用程序在运行时定期在后台运行一些任务。 @Peter,如何使用应用程序中的代码更改注册表?这种方法是否与

  • 问题内容: 我有一个Java应用程序。 该应用程序具有一个设置,该设置决定该应用程序是否在启动时启动。 目前,我可以通过在“启动项目”文件夹中放置/删除快捷方式来实现此目的。 但是,我想知道是否有更好的方法来处理此行为。 编辑 是的,它是Windows。抱歉,之前没有清除该内容。 该应用程序具有一个用户可以在其中触发动作的UI,并且该应用程序在运行时会定期在后台运行一些任务。 @Peter,如何在

  • 问题内容: 我正在尝试但未能成功在具有以下 依赖项的* Spring Data 和 Hibernate environmet中缓存查询: * 我的实体服务的Spring Data Repository(ServiceRepository)是 从中调用存储库的@Cacheable方法 我的缓存配置文件(jpa-context.xml)是 它的灵感来自spring-data-jpa-examples

  • 我使用Spring Boot 1.4.1和spring-boot-starter-data-jpa 当查询我的自定义方法时,比如'find byname(String name)',它不是缓存。

  • 我是appium的新手,目前正在尝试创建一些简单的测试。我的问题是我根本无法启动正在测试的应用程序,它唯一有效的时间是使用appium-dotnet-驱动程序解决方案中包含的演示应用程序通过github提供 https://github.com/appium/appium-dotnet-driver 我已经在我的Nexus 5和几个模拟器上尝试了2个不同的应用程序,但没有任何效果(请参阅下面的附加