복붙노트

[SPRING] Spring 캐시가 @Cacheable 주석에 null 값을 캐시하지 않도록 알려면 어떻게합니까?

SPRING

Spring 캐시가 @Cacheable 주석에 null 값을 캐시하지 않도록 알려면 어떻게합니까?

메서드가 null 값을 반환하는 경우 다음과 같은 메서드에 대해 @Cacheable 주석의 결과를 캐시하지 않도록 지정하는 방법이 있습니까?

@Cacheable(value="defaultCache", key="#pk")
public Person findPerson(int pk) {
   return getSession.getPerson(pk);
}

최신 정보: 지난 11 월 null 값 캐싱과 관련하여 제출 된 JIRA 문제는 아직 해결되지 않았습니다. [# SPR-8871] @Cachable 조건은 반환 값을 참조 할 수 있어야합니다 - Spring Projects Issue Tracker

해결법

  1. ==============================

    1.만 세, Spring 3.2에서 프레임 워크는 Spring SPEL을 사용하여 이것을 허용한다. Cacheable을 둘러싼 java 문서의 참고 사항 :

    만 세, Spring 3.2에서 프레임 워크는 Spring SPEL을 사용하여 이것을 허용한다. Cacheable을 둘러싼 java 문서의 참고 사항 :

    http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/cache/annotation/Cacheable.html

    중요한 측면은 메소드가 호출 된 후에 unless가 평가된다는 것입니다. 키가 이미 캐시에있는 경우 메서드가 실행되지 않으므로 완벽합니다.

    따라서 위의 예제에서는 다음과 같이 주석을 달았습니다 (#result는 메소드의 반환 값을 테스트하는 데 사용할 수 있습니다).

    @Cacheable(value="defaultCache", key="#pk", unless="#result == null")
    public Person findPerson(int pk) {
       return getSession.getPerson(pk);
    }
    

    이 조건은 null 캐싱을 허용하는 Ehcache와 같은 플러그 가능한 캐시 구현의 사용으로 인해 발생한다고 생각합니다. 유스 케이스 시나리오에 따라 이는 바람직하지 않을 수도 있습니다.

  2. ==============================

    2.이 답변을 업데이트하는 것은 지금 구식입니다. Spring 3.2 이상에서는 Tech Trip의 대답 인 OP : Accepted as free로 표시해주세요.

    이 답변을 업데이트하는 것은 지금 구식입니다. Spring 3.2 이상에서는 Tech Trip의 대답 인 OP : Accepted as free로 표시해주세요.

    나는 그것이 가능하다고 생각하지 않는다. @CacheEvict 매개 변수 beforeInvocation을 false로 설정하여 메소드를 호출 한 후에 실행될 수있는 조건부 Cache 축출이 Spring에서도 있지만, CacheAspectSupport 클래스를 검사하면 리턴 값이 아니라는 것을 알 수있다. 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();
    }
    
  3. ==============================

    3.스프링 주석

    스프링 주석

    @Cacheable(value="defaultCache", key="#pk",unless="#result!=null")
    

    작동하지 않으면 시도 할 수 있습니다.

    @CachePut(value="defaultCache", key="#pk",unless="#result==null")
    

    그것은 나를 위해 작동합니다.

  4. from https://stackoverflow.com/questions/12113725/how-do-i-tell-spring-cache-not-to-cache-null-value-in-cacheable-annotation by cc-by-sa and MIT license