@Cacheable and @CachePut. But, what about removing data from cache? Consider a call to delete the record from Service or DB, in which case, we would also want to delete that record from the cache.We have
@CacheEvict to our rescue. When a method is annotated with @CacheEvict, spring removes the data from the cache for the provided key, on the invocation of the method. @CacheEvict supports all the attributes that @Cacheable does. Plus it has a few more.Let's explore eviction through various examples.
First and foremost, the code we would use for our tests.
ActorService, that provides the persistence for movie actors.public class ActorService {
@Cacheable(value = "actors", key = "#name")
public Actor getActor(String name) {
//The print that proves the method is executed.
System.out.println("getting actor " + name);
//retrieve the actor from DB and return
return new Actor(name, Gender.MALE);
}
//other methods
}
And the code to run the tests.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.codelooru.cache");
ActorService service = context.getBean("actorService", ActorService.class);
service.getActors("sean");
service.getActors("meryl");
service.getActors("sean");
service.getActors("meryl");
On the initial run, we would see the following output. getting actor sean
getting actor meryl
CacheEvict with Key
removeActor method to the ActorService as shown below. The method is annotated with @CacheEvict with the value set to the cachename, from which the data needs to be evicted. @CacheEvict(value = "actors", key = "#name")
public void removeActor(String name) {
System.out.println("--removedActor--");
}
And modify the test code as below and run it
service.getActor("sean");
service.getActor("meryl");
service.getActor("sean");
service.getActor("meryl");
service.removeActor("sean");
service.getActor("sean");
service.getActor("meryl");
This would result in
getting actor sean
getting actor meryl
--removedActor--
getting actor sean
In this example, we called
removeActor with key = "sean", which removed sean from the cache. Therefore, the subsequent call to getActor for sean resulted in the execution of the method, but the call with "meryl" did not.CacheEvict with conditions
Let's add a condition for eviction
@CacheEvict(value = "actors", key = "#name", condition="#name == 'meryl'")
public void removeActor(String name)
Running the test code would result in the following.
getting actor sean
getting actor meryl
--removedActor--
This means that the call to
removeActor did not remove the data element from cache, as the condition was checking for the name to match 'meryl'.
Let's change the condition to 'sean'
@CacheEvict(value = "actors", key = "#name", condition="#name == 'sean'")
public void removeActor(String name)
Running the test code would result in the following
getting actor sean
getting actor meryl
--removedActor--
getting actor sean
Now, we see that the
removeActor did remove the data element for 'sean' from the cache.
unless works in a similar way, except that its expression evaluated after the execution of the method; thereby allowing you to use the result of the method in the expression. See Part3 for more details on how unless works.
CacheEvict with allEntries
removeActor as shown below.
@CacheEvict(value = "actors", allEntries = true)
public void removeActor(String name)
Running the test code results in the following output.
getting actor sean
getting actor meryl
--removedActor--
getting actor sean
getting actor meryl
As you see, setting the
allEntries attribute to true, removed all the data elements from the "actors" cache. Therefore, the subsequent calls with both sean and meryl result in the execution of the methods.
Final Notes
- Either
keyorallEntriesattribute should be present for cache eviction. - Do not use both
@Cacheableand@CacheEvicton a method. It does not solve any purpose. @CacheEvictdoes not support retention based eviction e.g. evict LeastRecentlyUsed, LeastFrequentlyUsed, etc. For such policies, you will have to rely on 3rd party cache providers like ehCache.
In the Spring Cache series so far (