我有两种方法来获取具有两个不同参数的实体。我还有一个使用其中一个参数的保存方法。如何在两个提取键下从缓存中逐出实体?例如见下文:
@Cacheable
public User getByUsername(String username);
@Cacheable
public User getByEmail(String email);
@CacheEvict(key="#entity.username")
User save(User entity);
在上面,对getByEmail的调用将返回过时日期。
答案 0 :(得分:9)
当然,有几种选择,但像往常一样, Spring 让你回来。
最简单,最简单的方法是在@Caching
方法上使用Spring的save
注释,就像这样......
@Caching(evict = {
@CacheEvict(cacheNames = "Users", key="#user.name"),
@CacheEvict(cacheNames = "Users", key="#user.email")
})
User save(User user);
为了供您参考,我创建了一个示例测试类,演示了这个工作here。
你会注意到我在UserRepository上使用 Spring的缓存抽象注释模仿了上面的例子。在这种情况下,我的repo由 Pivotal GemFire 支持,但任何数据存储都可以。我使用ConcurrentMap
作为我的缓存提供程序,使用Spring的ConcurrentMapCacheManager,但当然,任何缓存提供程序都可以。{/ p>
我的test case继续保存新 User
,确保用户尚未缓存。然后,测试继续执行查询方法(findByName
,findByEmail
),确保在每种情况下都适当地缓存用户实体。然后,我从基础数据存储中删除实体,并确保实体仍然被缓存。最后,在真实的时刻,我修改实体,重新保存实体,断言实体是由所有条目存储的,已从缓存中“逐出”。
在这种情况下,您还可以尝试将@CachePut
注释与2 @CacheEvict
注释结合起来作为另一种优化,这可以根据新的更新实体恢复缓存,例如。 ..
@Caching(
evict = {
@CacheEvict(cacheNames = "Users", key="#a0.name", beforeInvocation = true),
@CacheEvict(cacheNames = "Users", key="#a0.email", beforeInvocation = true)
},
put = {
@CachePut(cacheNames = "Users", key="#result.name"),
@CachePut(cacheNames = "Users", key="#result.email")
}
)
User save(User user);
注意:请注意beforeInvocation
注释@CacheEvict
属性的用户以及@CachePuts
但是,您可能希望根据需要将实体延迟添加到缓存中。
虽然,您可以假设实体经常被访问/使用,因为您的repo上的save
方法刚刚被调用,因此依赖您的基础数据存储(例如GemFire)来设置额外的驱逐(基于在溢出)/到期(基于LRU)设置,从而更好地管理您的系统资源(例如内存),同时仍保持最佳的应用程序性能。
深思熟虑。
希望这有帮助。