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

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

华凌
2023-03-14

我正在使用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中可能吗?

共有3个答案

米项禹
2023-03-14

为什么不将列表缓存为字符串?

@Cacheable(value = "my-cache-bucket:my-id-parameters", key = "{#id, #parameters}")
getMy(UUID id, String parameters) { ... }

使用喜欢:

getMy(randomUUID(), parametersList.toString());

您的缓存密钥如下所示:

"my-cache-bucket:my-id-parameters::3ce42cd9-99d4-1d6e-a657-832b4a982c72,[parameterValue1,parameter-value2]
钮兴安
2023-03-14

使用CachePut和helper方法,您可以非常简单地实现它,如下所示:

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

public void preloadCache(List<String>codes) {
    List<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) {    

请参阅:

  • https://github.com/spring-projects/spring-framework/issues/23221
  • https://github.com/qaware/collection-cacheable-for-spring

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

穆宏胜
2023-03-14

事实上,即使使用Spring的缓存抽象,这也是可能的,但不是现成的(OOTB)。本质上,您必须自定义Spring的缓存基础结构(下面将进一步解释)

默认情况下,Spring的缓存基础结构使用整个可缓存的方法参数参数作为缓存“键”,如下所述。当然,您也可以使用SpEL表达式或自定义键生成器实现自定义键分辨率,如本文所述。

尽管如此,这并不会将参数参数的集合或数组以及可缓存方法的返回值分解为单个缓存项(即基于数组/集合或映射的键/值对)。

为此,您需要Spring的缓存管理器(取决于您的缓存策略/提供者)和缓存接口的自定义实现。

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

我已经更新/清理了这个帖子的示例(有点)。

注意,我的示例扩展并定制了Spring框架本身中提供的ConcurrentMapCacheManager。

从理论上讲,您可以扩展/自定义任何CacheManager实现,例如Spring Data Redis中的Redis,此处(源代码),或Spring Data GemFire中的Pivotal GemFire的CacheManager,此处(源代码)。Pivotal gemFire的开源版本是Apache Geode,它有一个相应的Spring Data Geode项目,(Spring Data Geode中CacheManager的源代码,它与SD GemFire基本相同)。当然,您可以将这种技术应用于其他缓存提供程序... Hazelcast、Ehcache等。

然而,这项工作的真正核心是由Spring缓存接口的自定义实现(或更具体地说,基类)处理的。

无论如何,希望从我的示例中,您能够了解在应用程序中需要做什么来满足应用程序的缓存需求。

此外,您可以应用相同的方法来处理Maps,但我将把它留给您练习,;-)。

希望这有帮助!

干杯,约翰

 类似资料:
  • 问题内容: 我正在使用Spring Cache,在这里传递一组键,返回的是实体列表。我想让缓存框架了解返回列表中的每个元素都将与相应的代码一起缓存。目前看来,键是整个列表,如果我在随后的调用中缺少键,它将尝试重新加载整个集合。 另一个可能性是返回的是地图,类似地,我希望缓存足够智能,以仅查询以前从未查询过的项目,还可以使用键将每个项目缓存。 假设国家/地区类别如下所示: Spring Cache有

  • Contact实体定义了与两个MySQL表中存在的email和nickname类型的实体集合的关系。 我的问题是返回的结果集有重复的电子邮件和昵称。 当重复发生时,Hibernate正在运行以下操作。 问候你,伊恩。

  • 问题内容: 我想找到在其标签集中包含 所有 给定标签的项目。 以下是简化的类: 如果我这样尝试 我得到包含 任何 给定标签的项目。这不足为奇,但我希望包含 所有 给定标签的项目。所以我尝试另一种方式: 我收到错误消息。如果仅包含一个标签,它将起作用,但失败的原因不止于此。 如何在JPQL中表达呢? 问题答案: 诀窍是使用计数:

  • 问题内容: 尝试更新我的实体时遇到以下问题: 我有一个父实体,并且有一些子实体。当我尝试更新它时,我将获取所有要设置为此集合的引用并进行设置。 以下代码表示我的映射: 根据此,我尝试仅清理Set <..>:如何“可能”解决问题,但没有成功。 如果您有任何想法,请告诉我。 谢谢! 问题答案: 实际上,我的问题是关于实体的等于和哈希码。遗留代码会带来很多问题,永远不要忘记对其进行检查。我所做的只是保留

  • 我有一个包含元素列表的实体,现在我想搜索这些元素的属性。这个约束应该是“与”连接的。请看这些简单的例子: 现在我想找到某个城市的家长,比如说“BigCity”,孩子们在学校“AwesomeSchool”,他们在六年级一班。我只想通过CriteriaBuilder获得搜索结果。 到目前为止,我得到了: 不幸的是,这里有两个问题:-看起来我无法在列表属性上调用-这将返回所有孩子在“AwesomeSch