Spring boot @CachePut, how it works

10,265

Solution 1

1-@CachePut does not replace actual value, but put another value :delete key = "#setting.name" in that way keygenarator will use the hashcode of GlobalSettings(verify if the hashcode is implemented correctly)and also verify if the name of the cache "noTimeCache" is not specified to other methods.

2-see this link http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html if the "setting" parameter is an attribute in GlobalSettings you can change the SpEL expression #setting.getSetting().name() to #setting.setting.name

3-You can do the following if you are using java 6 (no idea if this is possible with java 7 or 8 ) :

public interface GlobalSettingsRepository extends JpaRepository<GlobalSettings, Long>{

@Override
@CacheEvict(value = {"noTimeCache"}, allEntries = true)
GlobalSettings save(GlobalSettings globalSettings);
}

Solution 2

Thanks for answers. It helps me solve problems.

@CachePut replace values, but there was a problem in keys. I use something like this:

@Cacheable(value = "globalSettings", unless = "#result == null")
@Query("SELECT gs.value FROM GlobalSettings gs WHERE gs.setting = ?1")
String getGlobalSettingValue(Settings setting);

Settings is enum and key for default is enum name, for example SYSTEM_STATUS.

and this:

@Cacheable(value = "globalSettings", key = "#setting.name()")
public String getGlobalSettingEnumValue(Settings setting) {
    return Settings.valueOf(setting.name()).getDefaultValue();
}

will also save key as STSYEM_STATUS.

Key's was the same but cache interprets this like 2 different cache values, I don't know why.

U can't use variable name in repository class like #setting, it must be argument index like #p0, probably beacause of spring data use his own proxy classes.

This solve all my problems and now cache work properly.

Share:
10,265
CSniper
Author by

CSniper

Updated on July 15, 2022

Comments

  • CSniper
    CSniper almost 2 years

    I'm trying to update values in spring cache, however @CachePut does not replace actual value, but put another value with the same key:

    Cachename: noTimeCache:

    • Key: SYSTEM_STATUS, val: ON
    • Key: SYSTEM_STATUS, val: OFF

    1.Why?

    My cache service:

    @CachePut(value = "noTimeCache", key = "#setting.getSetting().name()")
    public String updateGlobalCacheValue(GlobalSettings setting) {
        System.out.println("Setting: " + setting.getSetting().name() + ", val: " + setting.getValue());
        return setting.getValue();
    }
    

    I know it's looks funny but i need to work with jpa repositories. Maybe someone have better solution.

    2.Why can't I use function argument as @Cacheable key like this?

    @Cacheable(value = "noTimeCache", key = "#setting.name()", unless = "#result == null")
    @Query("SELECT gs.value FROM GlobalSettings gs WHERE gs.setting = ?1")
    String getGlobalSettingValue(Settings setting);
    

    It tells me setting is null.

    3.Is the way to override @Repositository interface methods, for example save() to add annotation @Cacheable to them?