【问题标题】:Spring boot @CachePut, how it worksSpring boot @CachePut,它是如何工作的
【发布时间】:2016-12-29 00:16:17
【问题描述】:

我正在尝试更新 spring 缓存中的值,但是 @CachePut 不会替换实际值,而是使用相同的键放置另一个值:

缓存名称:noTimeCache:

  • 键:SYSTEM_STATUS,值:ON
  • 键:SYSTEM_STATUS,值:OFF

1.为什么?

我的缓存服务:

@CachePut(value = "noTimeCache", key = "#setting.getSetting().name()")
public String updateGlobalCacheValue(GlobalSettings setting) {
    System.out.println("Setting: " + setting.getSetting().name() + ", val: " + setting.getValue());
    return setting.getValue();
}

我知道这看起来很有趣,但我需要使用 jpa 存储库。也许有人有更好的解决方案。

2.为什么我不能像这样使用函数参数作为@Cacheable 键?

@Cacheable(value = "noTimeCache", key = "#setting.name()", unless = "#result == null")
@Query("SELECT gs.value FROM GlobalSettings gs WHERE gs.setting = ?1")
String getGlobalSettingValue(Settings setting);

它告诉我设置为空。

3.是否有覆盖@Repositository接口方法的方式,比如save()给它们添加注解@Cacheable?

【问题讨论】:

  • 也许愚蠢的问题:你使用什么样的缓存(管理器)允许重复键?如果我没记错的话,默认的只是ConcurrentHashMap。如果你选择其他的,比如 ehCache 或 Redis,如果你将它设置为一个已经存在的键,它们也会覆盖现有的值。

标签: spring spring-boot spring-data-jpa spring-cache


【解决方案1】:

1-@CachePut 不替换实际值,而是放入另一个值:delete key = "#setting.name" 这样 keygenarator 将使用 GlobalSettings 的哈希码(验证哈希码是否正确实现)并验证是否缓存的名称“noTimeCache”未指定给其他方法。

2-查看此链接http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html 如果“setting”参数是 GlobalSettings 中的一个属性,您可以 将 SpEL 表达式 #setting.getSetting().name() 更改为 #setting.setting.name

3-如果您使用的是 java 6,您可以执行以下操作(不知道 java 7 或 8 是否可行):

public interface GlobalSettingsRepository extends JpaRepository<GlobalSettings, Long>{

@Override
@CacheEvict(value = {"noTimeCache"}, allEntries = true)
GlobalSettings save(GlobalSettings globalSettings);
}

【讨论】:

    【解决方案2】:

    感谢您的回答。它可以帮助我解决问题。

    @CachePut 替换值,但键有问题。我使用这样的东西:

    @Cacheable(value = "globalSettings", unless = "#result == null")
    @Query("SELECT gs.value FROM GlobalSettings gs WHERE gs.setting = ?1")
    String getGlobalSettingValue(Settings setting);
    

    设置是枚举,默认键是枚举名称,例如 SYSTEM_STATUS。

    还有这个:

    @Cacheable(value = "globalSettings", key = "#setting.name()")
    public String getGlobalSettingEnumValue(Settings setting) {
        return Settings.valueOf(setting.name()).getDefaultValue();
    }
    

    还将密钥另存为 STSYEM_STATUS。

    键是相同的,但缓存将其解释为 2 个不同的缓存值,我不知道为什么。

    你不能在repository class中使用#setting这样的变量名,它必须是#p0这样的参数索引,可能是因为spring data使用了他自己的代理类。

    这解决了我所有的问题,现在缓存可以正常工作了。

    【讨论】:

      猜你喜欢
      • 2023-03-30
      • 2019-01-27
      • 1970-01-01
      • 2021-03-10
      • 2018-05-27
      • 2019-07-16
      • 2015-04-15
      • 2015-10-16
      • 2021-05-21
      相关资源
      最近更新 更多