英文:
Spring share @Cachable and @CachePut key
问题
我正在尝试在我的项目中集成Spring缓存。我已经设置了一个Redis缓存管理器,它确实起作用。然而,这是我的场景:我有一个Setting
实体。我想要创建一个findAll
方法,可以返回所有设置,还有一个setSetting
方法,允许设置特定的设置。
这是我为getSettings
和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;
}
当我调用getSettings
时,在我的Redis中会得到一个setting::SimpleKey []
键(这是我的预期行为)。然而,当我调用setSetting
时,由于有额外的参数,导致不是覆盖setting::SimpleKey []
键,而是在Redis中得到另一个键:"setting::SimpleKey [name, foobar]"
(其中name和foobar是我传递给setSetting
的参数)。
我理解这是keyGenerator
的工作原理,但它似乎相当出乎意料,我不太理解如何设置我在findAll
中使用的原始键。我是否必须制作一个自定义的键生成器?
我将非常感谢任何帮助!
英文:
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!
答案1
得分: 2
为了使 setSetting
能够覆盖从 getSettings
返回的缓存值,两个方法都应该返回 List<Setting>
。在每次更新设置之前,确实需要清除现有的缓存值,例如:
@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. 更新设置的值(就像你的代码中已经完成的那样)并保存更改
...
this.repository.save(setting.get());
// 2. 返回设置的列表
return repository.findAll();
}
英文:
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();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论