Introduction to Spring Data Caching
Spring Data Caching provides a way to cache the results of expensive method calls and reuse them when the same inputs occur again, improving the performance of your application. This guide covers key concepts and steps for getting started with Spring Data Caching, including adding dependencies, enabling caching, defining cache configurations, and implementing caching in your application.
Key Concepts of Spring Data Caching
- Caching: Storing the results of expensive method calls and reusing them when the same inputs occur again.
- @EnableCaching: Annotation to enable Spring's annotation-driven cache management capability.
- @Cacheable: Annotation to indicate that the result of a method should be cached.
- @CacheEvict: Annotation to indicate that a cache entry should be evicted.
- @CachePut: Annotation to indicate that a method's result should be cached and update an existing cache entry.
Adding Dependencies
Include the appropriate Spring Data dependency for your cache provider in your pom.xml
file. For example, for EhCache:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
Enabling Caching
Enable caching in your Spring Boot application by adding the @EnableCaching
annotation to your main application class:
Example: Application.java
// Application.java
package com.example.myapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Defining Cache Configurations
Define your cache configurations in an XML or Java configuration file:
Example: ehcache.xml
<ehcache xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='http://www.ehcache.org/ehcache.xsd'>
<diskStore path='java.io.tmpdir'/>
<defaultCache maxElementsInMemory='10000' eternal='false'
timeToIdleSeconds='120' timeToLiveSeconds='120' overflowToDisk='true'/>
<cache name='users'
maxElementsInMemory='1000' eternal='false'
timeToIdleSeconds='300' timeToLiveSeconds='600'
overflowToDisk='true' diskPersistent='false'
memoryStoreEvictionPolicy='LRU'/>
</ehcache>
Implementing Caching in Your Application
Use the @Cacheable
, @CacheEvict
, and @CachePut
annotations in your service layer:
Example: UserService.java
// UserService.java
package com.example.myapp.service;
import com.example.myapp.model.User;
import com.example.myapp.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Cacheable(value = "users", key = "#id")
public Optional findUserById(Long id) {
return userRepository.findById(id);
}
@CachePut(value = "users", key = "#user.id")
public User saveUser(User user) {
return userRepository.save(user);
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
@CacheEvict(value = "users", allEntries = true)
public void evictAllCacheValues() {
// This will remove all entries from the "users" cache.
}
}
Testing Spring Data Caching
Test your Spring Data Caching setup to ensure it works as expected:
Example: UserServiceTests.java
// UserServiceTests.java
package com.example.myapp;
import com.example.myapp.model.User;
import com.example.myapp.repository.UserRepository;
import com.example.myapp.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.cache.CacheManager;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
@SpringBootTest
public class UserServiceTests {
@Autowired
private UserService userService;
@MockBean
private UserRepository userRepository;
@Autowired
private CacheManager cacheManager;
@Test
public void testFindUserById() {
User user = new User();
user.setId(1L);
user.setUsername("testuser");
user.setPassword("password");
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
// First call, should hit the repository
Optional foundUser = userService.findUserById(1L);
assertThat(foundUser).isNotEmpty();
assertThat(foundUser.get().getUsername()).isEqualTo("testuser");
verify(userRepository, times(1)).findById(1L);
// Second call, should hit the cache
foundUser = userService.findUserById(1L);
assertThat(foundUser).isNotEmpty();
assertThat(foundUser.get().getUsername()).isEqualTo("testuser");
verify(userRepository, times(1)).findById(1L); // still 1 time
}
@Test
public void testEvictCache() {
userService.evictAllCacheValues();
assertThat(cacheManager.getCache("users")).isNotNull();
assertThat(cacheManager.getCache("users").get(1L)).isNull();
}
}
Key Points
- Caching: Storing the results of expensive method calls and reusing them when the same inputs occur again.
- @EnableCaching: Annotation to enable Spring's annotation-driven cache management capability.
- @Cacheable: Annotation to indicate that the result of a method should be cached.
- @CacheEvict: Annotation to indicate that a cache entry should be evicted.
- @CachePut: Annotation to indicate that a method's result should be cached and update an existing cache entry.
- Include the appropriate Spring Data dependency for your cache provider in your
pom.xml
file. - Enable caching in your Spring Boot application by adding the
@EnableCaching
annotation to your main application class. - Define your cache configurations in an XML or Java configuration file.
- Use the
@Cacheable
,@CacheEvict
, and@CachePut
annotations in your service layer. - Test your Spring Data Caching setup to ensure it works as expected.
Conclusion
Spring Data Caching provides a way to cache the results of expensive method calls and reuse them when the same inputs occur again, improving the performance of your application. By understanding and implementing caching using the appropriate annotations, you can effectively manage and optimize data retrieval in your Spring Boot application. Happy coding!