In this tutorial, I will show you how to evict cache in Spring Boot using @CacheEvict.
Related Post:
– Spring Boot Redis Cache example
More Practice:
– Spring Boot WebFlux Rest API example
– Spring Boot Security and JWT tutorial with example
– Spring Boot @ControllerAdvice & @ExceptionHandler example
– @RestControllerAdvice example in Spring Boot
– Spring Boot Unit Test for Rest Controller
Contents
Why we need to evict cache
Caches are used to store frequently accessed data in a faster and easily retrievable location, improving overall system performance. However, as caches have a limited size, when they become full, new data cannot be stored until old data is evicted.
Cache eviction is necessary for several reasons, including:
- Limited cache space: Cache is a high-speed memory that stores frequently accessed data to reduce the response time of applications. However, caches have limited space, and when the cache is full, new data cannot be stored without removing some of the existing data. In such cases, the cache manager must decide which items to evict to make room for new items.
- Cache consistency: In some cases, the cache contains data that may become outdated or invalid due to changes in the underlying data source. If such data remains in the cache for an extended period, it can lead to inconsistencies and incorrect results. Thus, it is necessary to evict such data from the cache to maintain consistency.
- Cache performance: As the cache size grows, the time required to search for data in the cache also increases. If the cache size becomes too large, the search time may exceed the benefits of caching. In such cases, it may be necessary to evict some data from the cache to maintain its performance.
So, we need to evict cache to optimize the performance and efficiency of caching systems and ensure that cached data is up-to-date and relevant.
Spring @CacheEvict
In the Spring Framework, the @CacheEvict
annotation is used to remove one or more entries from a cache. When a method annotated with @CacheEvict
is called, Spring will remove the cached data associated with the specified cache name and key (or keys) along with the method execution.
Here are some useful @CacheEvict
parameters:
cacheNames
/value
(alias): the name of the cache to be evicted.key
: the key of the cache entry to be evicted. This parameter supports Spring Expression Language (SpEL) expressions, which can be used to dynamically determine the key at runtime.condition
: a SpEL expression that must be true in order for the cache entry to be evicted. This allows for conditional eviction of cache entries based on runtime conditions.beforeInvocation
: defaults to false, meaning that the cache eviction operation will occur after the method is invoked successfully.
Spring @CacheEvict example
This is the result when we retrieve a Tutorial from cache:
Before using @CacheEvict
, you update a Tutorial, for example.
Then you request the Tutorial again. If the cache TTL is not expired, the result data is not changed because the cache was not evicted.
Let’s use the Spring @CacheEvict
annotation:
public class TutorialService {
@Autowired
TutorialRepository tutorialRepository;
@Cacheable("tutorial")
public Optional<Tutorial> findById(long id) {
return tutorialRepository.findById(id);
}
@CacheEvict(value = "tutorial", key = "#tutorial.id")
public Tutorial update(Tutorial tutorial) {
return tutorialRepository.save(tutorial);
}
@CacheEvict(value = "tutorial", key = "#id")
public void deleteById(long id) {
tutorialRepository.deleteById(id);
}
}
The TutorialService
class has two methods annotated with @CacheEvict
:
deleteById(long id)
: delete a Tutorial by id.update(Tutorial tutorial)
: update a Tutorial.
@CacheEvict(value = "tutorial", key = "#id")
@CacheEvict(value = "tutorial", key = "#tutorial.id")
The key
parameter specifies cache entry (key) to be evicted. It’s the Id of the Tutorial passed as a parameter.
– If the method parameter is id
, the key is "#id"
– If the method parameter is tutorial
, the key should be "#tutorial.id"
So when the update
or deleteById
method is called, Spring will remove the corresponding entry from the "tutorial"
cache after the method is executed. If you want to evict cache before method invocation, set beforeInvocation
to true
.
The next time the findById
method is called with the same id
, it will execute the method and retrieve the updated data from the database, instead of returning the old data from the cache.
Now we have cache for 3 Tutorials with 3 keys:
If we run delete by id query for a specific Tutorial:
The “tutorial” cache with the key of id (tutorial::5
) was evicted:
@CacheEvict with multiple keys example
Assume that we have following data in cache:
We will use @CacheEvict
with multiple keys for the “tutorial”, “tutorials” and “published_tutorials” cache.
findAll() {
return tutorialRepository.findAll();
}
@Cacheable("tutorials")
public List<Tutorial> findByTitleContaining(String title) {
return tutorialRepository.findByTitleContaining(title);
}
@Cacheable("published_tutorials")
public List<Tutorial> findByPublished(boolean isPublished) {
return tutorialRepository.findByPublished(isPublished);
}
@CacheEvict(value = { "tutorial", "tutorials", "published_tutorials" }, allEntries = true)
public void deleteAll() {
tutorialRepository.deleteAll();
}
}
The deleteAll
method is annotated with @CacheEvict
and specifies allEntries = true
, which means that all entries in the “tutorial”, “tutorials”, “published_tutorials” cache will be removed when this method is called.
@CacheEvict condition example
Using @CacheEvict
with condition
allows you to specify a condition that must be met in order to remove the cache entry. This can be useful in scenarios where you want to selectively remove cache entries based on certain conditions, without invalidating the entire cache.
For example:
public class TutorialService {
@Autowired
TutorialRepository tutorialRepository;
@CacheEvict(value = "tutorial", condition = "#tutorial.published")
public Tutorial update(Tutorial tutorial) {
return tutorialRepository.save(tutorial);
}
}
The update()
method is annotated with @CacheEvict
and specifies a SpEL expression in the condition (#tutorial.published
). This means that the cache entry will only be removed if the published
property of the tutorial
parameter is true
. This is useful when you only want to remove entries under certain conditions, for example, when a tutorial’s status changes or when a tutorial is enabled/disabled.
Conclusion
Today you’ve known the reason why we need to evict cache, and way to use Spring @CacheEvict
annotation in Spring Boot application. We also make @CacheEvict
with multiple keys example.
Don’t forget to add @EnableCaching
to the configuration class or service class. It enables the use of Spring’s caching abstraction in your application, allows developers to annotate methods with caching annotations such as @Cacheable
and @CacheEvict
.
@Service
@EnableCaching
public class TutorialService {
}
For more detail about @Cacheable
annotation to tell Spring to cache the result of a method, please visit:
Spring Boot Redis Cache example
Source Code
The complete source code for this tutorial is on Github.
You can also apply the code easily on following Projects:
– Spring Boot 3 Rest API example
– Spring Boot Rest API with H2
– Spring Boot Rest API with MySQL
– Spring Boot Rest API with PostgreSQL
– Spring Boot Rest API with MongoDB
– Spring Boot Rest API with SQL Server
– Spring Boot Rest API with Cassandra
– Spring Boot Rest API with Oracle
Further Reading
Fullstack CRUD App:
– Spring Boot Thymeleaf example
– Vue + Spring Boot example
– Angular 8 + Spring Boot example
– Angular 10 + Spring Boot example
– Angular 11 + Spring Boot example
– Angular 12 + Spring Boot example
– Angular 13 + Spring Boot example
– Angular 14 + Spring Boot example
– Angular 15 + Spring Boot example
– React + Spring Boot example
More Practice:
– Spring Boot WebFlux Rest API example
– Secure Spring Boot with Spring Security & JWT Authentication
– Spring Boot Rest XML example – Web service with XML Response
– Spring Boot + GraphQL example
– Spring Boot File upload example
– Spring Boot Pagination and Sorting example
– Documentation: Spring Boot Swagger 3 example