带有项目/实体集合的Spring Cache

时间:2017-06-13 18:33:29

标签: java spring spring-cache

我正在使用Spring Cache,我在其中传递一组键,返回是一个实体列表。我想让缓存框架理解返回列表中的每个元素都要使用相应的代码进行缓存。目前,似乎关键是整个列表,如果我在后续调用中缺少一个键,它将尝试再次重新加载整个集合。

@Override
@Cacheable(value = "countries")
public List<Country> getAll(List<String>codes) {
    return countryDao.findAllInCodes(codes);
}

另一种可能性是返回是一个映射,同样我希望缓存足够智能,只能查询以前从未查询过的项目,也可以用它的密钥缓存每个项目。

@Override
@Cacheable(value = "countries")
public Map<String,Country> getAllByCode(List<String>codes) {
    return countryDao.findAllInCodes(codes);
}

假设国家/地区类似:

class Country{
  String code; 
  String fullName;
  long id;

... // getters setters constructurs etc.. 
}

Spring Cache可以实现吗?

2 个答案:

答案 0 :(得分:14)

事实上,即使使用Spring's Caching Abstraction,它也是可能的,但不是开箱即用(OOTB)。基本上,您必须自定义 Spring的缓存基础结构(下面将进一步说明)

通过默认 Spring的缓存基础结构使用整个@Cacheable方法参数参数作为缓存“key”,如here所述。当然,您也可以使用 SpEL表达式或自定义KeyGenerator实施来自定义密钥解析,如here所述。

仍然,参数参数的集合或数组与@Cacheable方法的返回值分解为单个缓存条目(即基于数组/集合或映射的键/值对)。

为此,您需要自定义 Spring的 CacheManager(取决于您的缓存策略/提供程序)和Cache接口。

  

注意:具有讽刺意味的是,这将是我第三次回答几乎相同的问题,首先是here,然后是here,现在这里,:-)。总之...

我已更新/清理了my example(有点)此帖子。

请注意my example extends and customizes Spring Framework 本身提供的ConcurrentMapCacheManager

从理论上讲,您可以扩展/自定义任何CacheManager实施,例如 Spring Data Redis 中的 Redis heresource )或 Pivotal GemFire的 CacheManager Spring Data GemFire heresource)中。 Pivotal GemFire 的开源版本是 Apache Geode ,它具有相应的 Spring Data Geode 项目,(<{3}}位于 Spring Data Geode ,与SD GemFire基本相同。当然,您可以将此技术应用于其他缓存提供商... Hazelcast,Ehcache等。

但是,工作的真正内容是由 Spring的 source for CacheManager界面的custom implementation(或更具体地说,base class)处理的。

无论如何,希望从Cache开始,您将能够找出在应用程序中需要做什么以满足应用程序的缓存要求。

此外,您可以采用相同的方法处理Maps,但我会将其作为练习留给您,; - )。

希望这有帮助!

干杯, 约翰

答案 1 :(得分:0)

使用@CachePut和辅助方法,您可以非常简单地实现它:

public List<Country> getAllByCode(List<String>codes) {
    return countryDao.findAllInCodes(codes);
}

public void preloadCache(List<String>codes) {
    Map<String,Country> allCountries = getAllByCode(codes);
    for (Country country : allCountries) {
        cacheCountry(country);
    }
}

@CachePut
public Country cacheCountry(Country country) {
    return country
}

注意

这只会将值添加到缓存,而不会删除旧值。您可以在添加新值之前轻松进行缓存逐出

选项2

有一个使它像这样工作的建议:

@CollectionCacheable
public List<Country> getAllByCode(List<String>codes) {    

请参阅:

如果您不耐烦,请从GitHub获取代码并在本地集成