如何告诉Spring cache不要在@Cacheable注释中缓存空值
有没有一种方法可以指定,如果该方法返回null值,那么对于这样的方法,不将结果缓存在@Cacheable注释中如何告诉Spring cache不要在@Cacheable注释中缓存空值,spring,caching,memcached,Spring,Caching,Memcached,有没有一种方法可以指定,如果该方法返回null值,那么对于这样的方法,不将结果缓存在@Cacheable注释中 @Cacheable(value="defaultCache", key="#pk") public Person findPerson(int pk) { return getSession.getPerson(pk); } 更新: 以下是去年11月提交的关于缓存空值的JIRA问题,该问题尚未解决: 更新对于Spring 3.2和更高版本,此答案现在已经过时,请参见技术旅行,
@Cacheable(value="defaultCache", key="#pk")
public Person findPerson(int pk) {
return getSession.getPerson(pk);
}
更新:
以下是去年11月提交的关于缓存空值的JIRA问题,该问题尚未解决:
更新对于Spring 3.2和更高版本,此答案现在已经过时,请参见技术旅行,OP:随时将其标记为已接受 我认为这是不可能的(即使Spring中有条件缓存逐出,可以在方法调用之后执行,而
@cacheexecute
参数beforeInvocation设置为false,这是默认值)检查CacheAspectSupport
类表明,返回值没有存储在InspectAfterCacheExecutes(ops.get(execute))之前的任何位置代码>呼叫
protected Object execute(Invoker invoker, Object target, Method method, Object[] args) {
// check whether aspect is enabled
// to cope with cases where the AJ is pulled in automatically
if (!this.initialized) {
return invoker.invoke();
}
// get backing class
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
if (targetClass == null && target != null) {
targetClass = target.getClass();
}
final Collection<CacheOperation> cacheOp = getCacheOperationSource().getCacheOperations(method, targetClass);
// analyze caching information
if (!CollectionUtils.isEmpty(cacheOp)) {
Map<String, Collection<CacheOperationContext>> ops = createOperationContext(cacheOp, method, args, target, targetClass);
// start with evictions
inspectBeforeCacheEvicts(ops.get(EVICT));
// follow up with cacheable
CacheStatus status = inspectCacheables(ops.get(CACHEABLE));
Object retVal = null;
Map<CacheOperationContext, Object> updates = inspectCacheUpdates(ops.get(UPDATE));
if (status != null) {
if (status.updateRequired) {
updates.putAll(status.cUpdates);
}
// return cached object
else {
return status.retVal;
}
}
retVal = invoker.invoke();
inspectAfterCacheEvicts(ops.get(EVICT));
if (!updates.isEmpty()) {
update(updates, retVal);
}
return retVal;
}
return invoker.invoke();
}
受保护对象执行(调用程序调用程序、对象目标、方法、对象[]参数){
//检查是否启用了方面
//以应对自动拉入AJ的情况
如果(!this.initialized){
返回invoker.invoke();
}
//获得后备班
Class targetClass=aopproxutils.ultimateTargetClass(目标);
if(targetClass==null&&target!=null){
targetClass=target.getClass();
}
最终集合cacheOp=GetCacheOperationsSource().getCacheOperations(方法,targetClass);
//分析缓存信息
如果(!CollectionUtils.isEmpty(cacheOp)){
Map ops=createOperationContext(cacheOp、方法、参数、目标、targetClass);
//从驱逐开始
检查缓存收回之前(操作获取(收回));
//后续可缓存
CacheStatus status=inspectCacheables(ops.get(CACHEABLE));
Object retVal=null;
映射更新=检查缓存更新(ops.get(UPDATE));
如果(状态!=null){
如果(需要状态更新){
更新.putAll(状态.cUpdates);
}
//返回缓存对象
否则{
returnstatus.retVal;
}
}
retVal=invoker.invoke();
检查收回(操作获取(收回));
如果(!updates.isEmpty()){
更新(更新,检索);
}
返回返回;
}
返回invoker.invoke();
}
万岁,从Spring 3.2开始,框架允许使用Spring SPEL和实现这一点,除非
。java文档中关于可缓存的注释:
公共抽象字符串,除非
用于否决方法缓存的Spring表达式语言(SpEL)属性
与condition()不同,此表达式是在调用方法后计算的,因此可以引用结果。默认值为“”,这意味着缓存永远不会被否决
重要的方面是,除非在调用方法后对进行评估。这非常有意义,因为如果密钥已经在缓存中,则该方法将永远不会执行
因此,在上面的示例中,您可以简单地注释如下(#result可用于测试方法的返回值):
我可以想象,这种情况是由于使用可插拔缓存实现(如Ehcache)而产生的,Ehcache允许缓存空值。根据您的用例场景,这可能是可取的,也可能不是可取的。
@Cacheable(value="defaultCache", key="#pk",unless="#result!=null")
不起作用,您可以尝试:
@CachePut(value="defaultCache", key="#pk",unless="#result==null")
这对我很有用。嗨,我想你应该接受Tech Trip的答案,因为它与当前版本的Spring更相关。嗨,我有一个场景,redis缓存服务器缓存异常。我必须避免将异常缓存到服务器。我可以为此使用“除非”参数吗?是否可以在“除非”中提及例外情况?请分享你的建议。非常感谢JSR107提供了一种机制,可以始终调用带注释的方法,并且仍然通过cacheResult#skipGet缓存结果。根据skipGet上的API,如果为true,则也会跳过对抛出异常的调用前检查。但是,如果在调用过程中抛出异常,它将按照标准异常缓存规则进行缓存,因此可能无法满足您的需要。然而,使用JSR107,您可以显式地排除配置上的某些异常,这可能会让您有继续的余地。(参见NonCacheXceptions)Spring的抽象提供了JSR107注释支持。仅供其他人参考-还有一个条件参数,也可以使用。在我的例子中,我需要condition=“#pk!=null”
,这样当参数为null
时,缓存不会抛出hv000028:isvalid调用期间出现意外异常
:)我复制粘贴了您的代码,发现出现了意外错误(type=Internal Server error,status=500)。为缓存操作返回的Null键(可能您在没有调试信息的类上使用命名参数?)Builder[public java.util.mappover@tftd建议使用条件=“#pk!=Null”。如果您需要使用“sync”作为“除非”在使用“sync”时不起作用,这很有用。您的意思是除非=“#result==Null”
?除非结果否则缓存!=null\u表示如果结果==null,则缓存。因此,正确的表达式是除非=“\result==null”
这表示除非结果否则缓存==null,这表示如果结果,则缓存!=null。
@CachePut(value="defaultCache", key="#pk",unless="#result==null")