首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >@CacheEvict的Gemfire EntryNotFoundException

@CacheEvict的Gemfire EntryNotFoundException
EN

Stack Overflow用户
提问于 2016-10-03 11:26:22
回答 1查看 448关注 0票数 0

简而言之,当在方法上调用@CacheEvict时,如果找不到条目的键,则Gemfire将抛出EntryNotFoundException。

现在详细的说,

我有个课

代码语言:javascript
复制
class Person {

 String mobile;
 int dept;
 String name;

}

我有两个缓存区域定义为personRegion和personByDeptRegion,服务如下

代码语言:javascript
复制
@Service
class PersonServiceImpl {

   @Cacheable(value = "personRegion")
   public Person findByMobile(String mobile) {

      return personRepository.findByMobile(mobile);

   }


   @Cacheable(value = "personByDeptRegion")
   public List<Person> findByDept(int deptCode) {

      return personRepository.findByDept(deptCode);

   }


   @Caching(
      evict = { @CacheEvict(value = "personByDeptRegion", key="#p0.dept"},
      put = { @CachePut(value = "personRegion",key = "#p0.mobile")}

   )
   public Person updatePerson(Person p1) {

      return personRepository.save(p1);

   }

}

当调用updatePerson时,如果personByDeptRegion中没有条目,这将引发一个异常,即键1的EntryNotFoundException (或其他什么是dept代码)。在调用@Cacheable方法并希望避免此异常之前,很有可能调用此方法。在给定区域不存在密钥时,我们是否可以调整Gemfire行为以优雅地返回?或者,我也渴望知道是否有一个更好的实现上述方案使用Gemfire作为缓存。

春季数据Gemfire : 1.7.4

Gemfire版本: v8.2.1

注:以上代码仅用于表示目的,在实际项目中,我有多个具有相同问题的服务。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-04 04:43:08

首先,我赞扬您在应用程序@Service组件上使用Spring的缓存注释。开发人员常常在他们的存储库中启用缓存,我认为这是不好的形式,特别是在复杂的业务规则(甚至是附加的IO;例如从服务组件调用web服务)发生之前或之后,尤其是在不影响(或确定)缓存行为的情况下。

我还认为您的缓存UC (更新一个缓存(personRegion),而在数据存储更新上使另一个缓存(personByDeptRegion)无效)通过使用CacheEvict跟踪CachePut似乎是合理的。不过,我要指出,@Caching注释的目的似乎是将相同类型的多个缓存注释(例如,多个@CacheEvict或多个@CachePut)组合在一起,就像核心SpringFramework参考指南中所解释的那样。尽管如此,没有什么能阻止你打算使用。

我根据上面的示例创建了类似的测试类这里,以验证问题。实际上,jonDoeUpdateSuccessful测试用例失败( GemFire EntryNotFoundException,如下所示),因为在更新之前,Department "R&D“中没有人被缓存在"DepartmentPeople”GemFire区域中,这与janeDoeUpdateSuccessful测试用例不同,后者导致在更新之前填充缓存(即使条目没有值,这并不重要)。

代码语言:javascript
复制
com.gemstone.gemfire.cache.EntryNotFoundException: RESEARCH_DEVELOPMENT
    at com.gemstone.gemfire.internal.cache.AbstractRegionMap.destroy(AbstractRegionMap.java:1435)

注意:我的测试使用GemFire作为“缓存提供者”和记录系统(SOR)。

问题在于SDG在GemfireCache.evict(key)实现中使用了GemfireCache.evict(key),而不是,也许更合适的是使用Region.remove(key)

GemfireCache.evict(key)从一开始就用Region.destroy(key)实现。但是,直到Region.remove(key) v5.0才引入GemFire。不过,除了Region.destroy(key)Region.remove(key)抛出的EntryNotFoundException之外,我看不出两者之间有什么明显的区别。本质上,它们都破坏本地条目(键和值),并将操作分发到集群中的其他缓存(提供非LOCAL 作用域 )。

因此,我已经提交了SGF-539文件,将SDG更改为在GemfireCache.evict(key)中调用Region.remove(key),而不是Region.destroy(key)

至于解决办法,基本上只有两件事你可以做:

  1. 重组您的代码和使用@CacheEvict注释,和/或..。
  2. 利用condition on @CacheEvict

不幸的是,不能使用类类型来指定condition,这类似于Spring 条件 (除了SpEL之外),但是这个接口是为了另一个目的,而@CacheEvictcondition属性不接受类类型。

目前,我还没有一个很好的例子来说明这是如何工作的,所以我正在SGF-539上继续前进。

您可以按照此票证获得更多详细信息和进展。

很抱歉给您带来不便。

-John

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39830488

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档