CSniper
CSniper

Reputation: 353

Spring boot @CachePut, how it works

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:

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?

Upvotes: 4

Views: 18902

Answers (2)

CSniper
CSniper

Reputation: 353

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.

Upvotes: 2

SEY_91
SEY_91

Reputation: 1687

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);
}

Upvotes: 1

Related Questions