Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring share @Cachable and @CachePut key

I'm trying to integrate Spring cache within my project. I've set up a Redis cache manager and it indeed works. However, this is my scenario: I have a Setting entity. I want to make a findAll method that can return all of the settings and a setSetting which allows to set a specific setting.

This is the code I've defined for getSettings and setSetting:

  @Cacheable(value = "setting")
  public List<Setting> getSettings() {
    return repository.findAll();
  }

  @CachePut("setting")
  public Optional<Setting> setSetting(String key, Object value) {
    var setting = this.repository.findByIdentifier(key);
    if (setting.isEmpty()) {
      return Optional.empty();
    }

    try {
      setting.get().setValue(mapper.writeValueAsString(value));
    } catch (JsonProcessingException e) {
      LOG.error("Could not serialize the value: {}", value);
      return Optional.empty();
    }

    this.repository.save(setting.get());
    return setting;
  }

When I call to getSettings I get a setting::SimpleKey [] key in my Redis (that's my expected behaviour). However, when I call to setSetting, because of the extra argument, instead of overrding the setting::SimpleKey [] key, I end up with another key in Redis: "setting::SimpleKey [name, foobar]" (where name and foobar are the arguments I've sent to setSetting`).

I understand that it's how kecusyGenerator works, but it seems quite unexpected and I quite don't understand how to set the original key I've used in findAll. Do I have to make a custom key generator?

I'll appriciate any help!

like image 615
OzB Avatar asked Oct 23 '25 16:10

OzB


2 Answers

In order for setSetting to override the cached value returned from getSettings both methods should return the List<Setting>. You do need to evict the existing cached values before each update of setting e.g.

@Cacheable(value = "setting")
public List<Setting> getSettings() {
  return repository.findAll();
}

@CacheEvict(value = "setting", allEntries = true, beforeInvocation = true)
@Cacheable(value = "setting", key = "T(org.springframework.cache.interceptor.SimpleKey).EMPTY")
public List<Setting> setSetting(String key, Object value) {
  // 1. update the setting value (as already done in your code) and save changes
  ...
  this.repository.save(setting.get());

  // 2. Return the list of settings
  return repository.findAll();
}
like image 147
Igor Avatar answered Oct 26 '25 06:10

Igor


In order for setSetting to override the cached value returned from getSettings both methods should return the List<Setting>. You do need to evict the existing cached values before each update of setting e.g.

@Cacheable(value = "setting")
public List<Setting> getSettings() {
  return repository.findAll();
}

@CacheEvict(value = "setting", allEntries = true, beforeInvocation = true)
@Cacheable(value = "setting", key = "T(org.springframework.cache.interceptor.SimpleKey).EMPTY")
public List<Setting> setSetting(String key, Object value) {
  // 1. update the setting value (as already done in your code) and save changes
  ...
  this.repository.save(setting.get());

  // 2. Return the list of settings
  return repository.findAll();
}
like image 36
Igor Avatar answered Oct 26 '25 06:10

Igor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!