2.6 Caching
For read-heavy APIs, reference data, or statistics, caching reduces DB and external calls and improves latency. Spring offers declarative caching (@Cacheable) and a CacheManager abstraction.
Reference: Spring Boot 3.2.x, spring-boot-starter-cache
1. Dependency and Enabling Cache
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-cache'
}
@SpringBootApplication
@EnableCaching // enable caching
public class Application { ... }
2. Local Cache (Caffeine) — Recommended Default
Use Caffeine for in-memory cache without a separate server.
implementation 'com.github.ben-manes.caffeine:caffeine'
spring:
cache:
type: caffeine
cache:
caffeine:
spec: maximumSize=500,expireAfterWrite=10m
maximumSize=500: Keep up to 500 entriesexpireAfterWrite=10m: Expire 10 minutes after write
3. @Cacheable
Cache method return values; repeated calls with the same arguments are served from cache.
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id")
public Product findById(Long id) {
return productRepository.findById(id).orElseThrow();
}
@Cacheable(value = "productList", key = "#categoryId + '-' + #page")
public List<Product> findByCategory(Long categoryId, Pageable page) {
return productRepository.findByCategoryId(categoryId, page);
}
}
- value: Cache name (namespace)
- key: Cache key as SpEL expression. Omit to use default key derived from arguments.
4. @CacheEvict
Remove cache entries when data changes.
@CacheEvict(value = "products", key = "#product.id")
public void update(Product product) {
productRepository.save(product);
}
@CacheEvict(value = "products", allEntries = true) // clear entire cache
public void deleteAllByCategory(Long categoryId) {
productRepository.deleteByCategoryId(categoryId);
}
- allEntries = true: Delete all entries for the given cache name
5. @CachePut
Always run the method and put/overwrite the return value in cache. Use this to "reflect changes in cache immediately after saving".
@CachePut(value = "products", key = "#result.id")
public Product save(Product product) {
return productRepository.save(product);
}
6. Redis (Distributed)
For multiple servers sharing the same cache, use Redis.
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
spring:
cache:
type: redis
data:
redis:
host: localhost
port: 6379
- Keep
@Cacheable,@CacheEvictetc. as-is and simply switch CacheManager to Redis. - Set TTL via Redis config or RedisCacheConfiguration corresponding to each
@Cacheablecache name.
7. condition and unless
- condition: SpEL; only cache when true.
- unless: SpEL; do not cache when true.
@Cacheable(value = "users", key = "#id", unless = "#result == null")
public User findById(Long id) { ... }
If the cache key is simple, key can be omitted. For complex keys or null exclusion, use condition/unless. For Redis, always set TTL and memory policy appropriate for your production environment.