Is er een manier om aan te geven dat als de methode een null-waarde retourneert, het resultaat dan niet in de @Cacheable-annotatie wordt opgeslagen voor een methode als deze?
@Cacheable(value="defaultCache", key="#pk")
public Person findPerson(int pk) {
return getSession.getPerson(pk);
}
Bijwerken:
hier is het JIRA-probleem dat afgelopen november is ingediend met betrekking tot het cachen van de null-waarde, die nog niet is opgelost:
[#SPR-8871] @Cachable-voorwaarde moet het mogelijk maken om naar de retourwaarde te verwijzen – Spring Projects Issue Tracker
Antwoord 1, autoriteit 100%
Hoera, vanaf Spring 3.2 staat het framework dit toe met Spring SPEL en unless
. Opmerking uit het java-document rond Cacheable:
openbare abstracte tekenreeks tenzij
Spring Expression Language (SpEL)-kenmerk dat wordt gebruikt om methodecaching te weigeren.
In tegenstelling tot condition(), wordt deze expressie geëvalueerd nadat de methode is aangeroepen en kan daarom verwijzen naar het resultaat. De standaardwaarde is “”, wat betekent dat caching nooit wordt verboden.
Het belangrijke aspect is dat unless
wordt geëvalueerd nadat de methode is aangeroepen. Dit is volkomen logisch omdat de methode nooit wordt uitgevoerd als de sleutel zich al in de cache bevindt.
Dus in het bovenstaande voorbeeld zou je gewoon als volgt annoteren (#result is beschikbaar om de geretourneerde waarde van een methode te testen):
@Cacheable(value="defaultCache", key="#pk", unless="#result == null")
public Person findPerson(int pk) {
return getSession.getPerson(pk);
}
Ik kan me voorstellen dat deze toestand voortkomt uit het gebruik van pluggable cache-implementaties zoals Ehcache die het cachen van nulls mogelijk maakt. Afhankelijk van uw gebruiksscenario kan dit al dan niet wenselijk zijn.
Antwoord 2, autoriteit 4%
updatedit antwoord is nu verouderd, zie voor lente 3.2 en later Tech Trip’s antwoord, OP: markeer het gerust als geaccepteerd.
Ik denk niet dat het mogelijk is (ook al is er voorwaardelijke Cache-uitzetting in Spring die kan worden uitgevoerd na het aanroepen van de methode met @CacheEvict
parameter beforeInvocationingesteld op false , wat de standaardwaarde is) als de klasse CacheAspectSupport
wordt onderzocht, blijkt dat de geretourneerde waarde nergens is opgeslagen vóór de aanroep inspectAfterCacheEvicts(ops.get(EVICT));
.
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();
}
Antwoord 3, autoriteit 3%
Als lente-annotatie
@Cacheable(value="defaultCache", key="#pk",unless="#result!=null")
werkt niet, je kunt het proberen:
@CachePut(value="defaultCache", key="#pk",unless="#result==null")
Het werkt voor mij.