Spring @CacheEvict example

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


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:

spring-cacheevict-example-cache-hit

Before using @CacheEvict, you update a Tutorial, for example.

spring-cacheevict-example-cache-update

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.

spring-cacheevict-example-cache-hit

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.
  • @CacheEvict(value = "tutorial", key = "#id")

  • update(Tutorial tutorial): update a Tutorial.
  • @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.

spring-cacheevict-example-cache-eviction

Now we have cache for 3 Tutorials with 3 keys:

spring-cacheevict-example-keys

If we run delete by id query for a specific Tutorial:

spring-cacheevict-example-cache-eviction-request

The “tutorial” cache with the key of id (tutorial::5) was evicted:

spring-cacheevict-example-cache-eviction-key

@CacheEvict with multiple keys example

Assume that we have following data in cache:

cacheevict-multiple-keys

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-multiple-keys-example

@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