Spring Boot Caching with Example

In this Spring boot tutorial, learn to manage the application caches using its built-in support. Most of the caching features are autoconfigured and need very little or no configuration.

Caching is a mechanism to enhance the performance of a system. It is a temporary memory that lies between the application and the persistent database. Cache memory stores recently used data items in order to reduce the number of database hits as much as possible.

1. Maven

Include the latest version of spring-boot-starter-cache dependency that transitively includes spring-context-support and spring-context modules. Both context modules provide the necessary classes and interfaces for handling the caching feature.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2. Enable or Disable Caching

To enable caching, use @EnableCaching annotation on any @Configuration class.

@Configuration
@EnableCaching
public class CacheConfig {
  ...
}

If none of the cache providers are found, by default, a simple implementation using a ConcurrentHashMap as the cache store is configured. We can programmatically configure the ConcurrentMapCacheManager bean, if required.

@Configuration
@EnableCaching
public class CacheConfig {

  @Bean
  public CacheManager cacheManager() {
      return new ConcurrentMapCacheManager("employees");
  }
}

If we want to disable caching in any environment then use spring.cache.type property.

spring.cache.type=none

3. Configuring the Cache Provider

Spring boot needs an underlying cache provider that can store and manage the cached objects and support lookups. Spring boot autoconfigures one of these providers with default options if it is present in the classpath and we have enabled cache by @EnableCaching.

  • JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)
  • EhCache (example)
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine (example)
  • Simple cache

To customize the configuration of any of the above providers, we can place the corresponding configuration file in the /resources folder and supply the config location to Spring boot.

For example, to customize Infinispan, put the infinispan.xml with custom configuration and provide the config location in application.properties.

spring.cache.infinispan.config=infinispan.xml

For details information, we can see the official spring boot documentation here.

4. Spring Cache Annotations

After enabling the caching, we can use the following caching annotations for adding and evicting the objects from the cache:

  • @Cacheable: Triggers cache population.
  • @CacheEvict: Triggers cache eviction.
  • @CachePut: Updates the cache without interfering with the method execution.
  • @Caching: Regroups multiple cache operations to be applied on a method.
  • @CacheConfig: Shares some standard cache-related settings at the class level.

Note that we can achieve similar functionality through XML configuration as well, but it is not recommended anymore.

4.1. @Cacheable

It is used on the method level to let spring know that the response of the method is cacheable. Spring intercepts the request/response of this method and stores the response in the cache by the name specified in the annotation attribute e.g. @Cacheable(“employees”).

@Cacheable("employees")
public Optional<Employee> getEmployeeById(Long id) {
  return repository.findById(id);
}

Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for cache access. By default, Spring uses the method parameters to form the cache keys as follows:

  • If no params are given, return SimpleKey.EMPTY.
  • If only one param is given, return that instance.
  • If more than one param is given, return a SimpleKey that contains all parameters.

It is very necessary to understand that keys must implement valid hashCode() and equals() methods contract for correct lookups.

@Cacheable(value = "employees", key = "#id")
public Optional<Employee> getEmployeeById(Long id) {...}

@Cacheable(value = "employees", key = "#department.id")
public List<Employee> getEmployeesByDepartmentId(Department department) {...}

We can also do the caching only when a certain condition is satisfied. In the following example, we are caching when the employee id is greater than 0;

@Cacheable(value = "employees", key = "#id", condition="#id > 0")
public Optional<Employee> getEmployeeById(Long id) {...}

4.2. @CachePut

The @CachePut annotation is very similar to the @Cacheable annotation except the annotated method is always executed irrespective of whether the cache key is present in the cache or not. It supports the same options as @Cacheable.

@CachePut(cacheNames = "employees", key = "#employee.id")
public Employee updateEmployee(Employee employee) {...}

4.3. @CacheEvict

This annotation is helpful in evicting (removing) the cache previously loaded. When @CacheEvict annotated methods will be executed, it will clear the cache matched with a cache name, cache key or a condition to be specified.

@CacheEvict(cacheNames="employees", key="#id") 
public void deleteEmployee(Long id) {...}

The @CacheEvict annotation offers an extra parameter ‘allEntries’ for evicting the whole specified cache, rather than a key in the cache.

@CacheEvict(cacheNames="employees", allEntries=true) 
public void deleteAllEmployees() {...}

4.4. @Caching

The @Caching annotation is needed to group multiple annotations when we need to use multiple cache annotations in a single method. In the following example, we are using the @CacheEvict annotation, twice.

@Caching(evict = {
    @CacheEvict(cacheNames = "departments", allEntries = true), 
    @CacheEvict(cacheNames = "employees", key = "...")})
public boolean importEmployees(List<Employee> data) { ... }

4.5. @CacheConfig

This annotation allows us to specify some of the cache configurations at the class level, so we do not have to repeat them multiple times over each method.

@Service
@CacheConfig(cacheNames={"employees"})
public class EmployeeService {

  @Autowired
  EmployeeRepository repository;

  @Cacheable(key = "#id")
  public Optional<Employee> getEmployeeById(Long id) { ... }

  @CachePut(key = "#employee.id")
  public Employee updateEmployee(Employee employee) { ... }
}

5. Conclusion

In this Spring Boot tutorial, we learned to enable and configure the caching functionality in a Spring boot application with examples. We learned about various caching-related classes and annotations and how to use them effectively.

In this post, we have used the fallback cache provider, that is ConcurrentHashMap in the background. The next step for you would be to configure other supported cache engines like Redis, Ehcache etc.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
8 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode