Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring cache all elements in list separately

Tags:

I'm trying to add caching to a CRUD app, I started doing something like this:

@Cacheable("users") List<User> list() {     return userRepository.findAll() } @CachePut(value = "users", key = "#user.id")  void create(User user) {     userRepository.create(user) } @CachePut(value = "users", key = "#user.id")  void update(User user) {     userRepository.update(user) } @CacheEvict(value = "users", key = "#user.id")  void delete(User user) {     userRepository.delete(user) } 

The problem I have is that I would like that create/update/delete operations can update the elements already stored in the cache for the list() operation (note that list() is not pulling from database but an data engine), but I am not able to do it.

I would like to cache all elements returned by list() individually so all other operations can update the cache by using #user.id. Or perhaps, make all operations to update the list already stored in cache.

I read that I could evict the whole cache when it is updated, but I want to avoid something like:

@CacheEvict(value = "users", allEntries=true)  void create(User user) {     userRepository.create(user) } 

Is there any way to create/update/remove values within a cached collection? Or to cache all values from a collection as individual keys?

like image 482
Federico Piazza Avatar asked Jul 09 '18 02:07

Federico Piazza


1 Answers

I'll self answer my question since no one gave any and could help others.

The problem I had when dealing with this issue was a problem of misconception of Cache usage. My need posted on this question was related to how to update members of a cached list (method response). This problem cannot be solved with cache, because the cached value was the list itself and we cannot update a cached value partially.

The way I wanted to tackle this problem is related to a "map" or a distributed map, but I wanted to use the @Cacheable annotation. By using a distributed map would have achieved what I asked in my question without using @Cacheable. So, the returned list could have been updated.

So, I had (wanted) to tackle this problem using @Cacheable from other angle. Anytime the cache needed to update I refreshed it with this code.

I used below code to fix my problem:

@Cacheable("users") List<User> list() {     return userRepository.findAll() } // Refresh cache any time the cache is modified @CacheEvict(value = "users", allEntries = true")  void create(User user) {     userRepository.create(user) } @CacheEvict(value = "users", allEntries = true")  void update(User user) {     userRepository.update(user) } @CacheEvict(value = "users", allEntries = true")  void delete(User user) {     userRepository.delete(user) } 

In addition, I have enabled the logging output for spring cache to ensure/learn how the cache is working:

# Log Spring Cache output logging.level.org.springframework.cache=TRACE 
like image 191
Federico Piazza Avatar answered Sep 27 '22 23:09

Federico Piazza