Published: March 25, 2025
Now that we’ve integrated caching providers like Ehcache and Redis with Hibernate, it’s time to learn how to monitor and tune caching performance. Cache statistics provide critical insight into cache behavior — helping us optimize hit rates, reduce latency, and avoid stale data.
Why Tune Cache Performance?
Caching isn’t “set and forget.” Poorly tuned caches can cause:
- High cache miss rates → More DB queries, slower response
- Inefficient memory usage → Out of memory or excessive GC
- Stale or inconsistent data
Tracking cache stats lets you spot bottlenecks and optimize configurations.
1. Enabling Hibernate Cache Statistics
To collect stats, enable them in Hibernate’s configuration:
spring.jpa.properties.hibernate.generate_statistics=true
You can also enable query plan caching stats:
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
2. Accessing Cache Statistics Programmatically
Hibernate’s Statistics interface exposes detailed metrics.
Example in a Spring Boot service:
@Service
public class CacheStatsService {
@Autowired
private EntityManagerFactory entityManagerFactory;
public void printCacheStats() {
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
Statistics stats = sessionFactory.getStatistics();
System.out.println("Second Level Cache Hit Count: " + stats.getSecondLevelCacheHitCount());
System.out.println("Second Level Cache Miss Count: " + stats.getSecondLevelCacheMissCount());
System.out.println("Second Level Cache Put Count: " + stats.getSecondLevelCachePutCount());
System.out.println("Entity Fetch Count: " + stats.getEntityFetchCount());
System.out.println("Query Execution Count: " + stats.getQueryExecutionCount());
}
}
Call this method periodically or expose via an actuator endpoint to monitor live metrics.
3. Key Metrics to Monitor
| Metric | Meaning | Desired Direction |
|---|---|---|
| Second Level Cache Hit Count | Number of cache hits | High |
| Second Level Cache Miss Count | Number of cache misses | Low |
| Second Level Cache Put Count | Number of puts to cache | Balanced (depends) |
| Entity Fetch Count | How often entities are fetched from DB | Low (if cache effective) |
| Query Execution Count | Number of executed queries | Low |
4. Using Ehcache Statistics
If using Ehcache, enable detailed monitoring in ehcache.xml:
<management enabled="true" />
Ehcache provides a JMX MBean you can query for stats like hits, misses, evictions.
Example accessing Ehcache stats via JMX console or programmatically:
CacheStatistics stats = cache.getStatistics();
System.out.println("Ehcache Hit Count: " + stats.getCacheHits());
System.out.println("Ehcache Miss Count: " + stats.getCacheMisses());
5. Tuning Cache Based on Stats
- Low hit rate: Increase cache size or adjust TTL.
- High eviction rate: Cache too small; increase heap or redistribute data.
- High put count but low hit count: Possibly caching rarely used entities; consider disabling cache on those.
- High stale data risk: Reduce TTL or use cache invalidation strategies.
6. Using Redis Metrics
If using Redis, monitor cache stats via:
- Redis CLI commands (
INFO stats) - Redis monitoring tools like RedisInsight
- Application metrics exported via Micrometer and Spring Boot Actuator
7. Example: Actuator Endpoint for Cache Stats
Add a simple REST controller exposing cache stats:
@RestController
@RequestMapping("/cache-stats")
public class CacheStatsController {
@Autowired
private CacheStatsService cacheStatsService;
@GetMapping
public ResponseEntity<Map<String, Object>> getStats() {
Map<String, Object> stats = new HashMap<>();
SessionFactory sessionFactory = ((SessionFactory)cacheStatsService.entityManagerFactory.unwrap(SessionFactory.class));
Statistics statistics = sessionFactory.getStatistics();
stats.put("secondLevelCacheHitCount", statistics.getSecondLevelCacheHitCount());
stats.put("secondLevelCacheMissCount", statistics.getSecondLevelCacheMissCount());
stats.put("secondLevelCachePutCount", statistics.getSecondLevelCachePutCount());
return ResponseEntity.ok(stats);
}
}
Summary
Performance tuning of Hibernate caches is an ongoing process. By enabling and monitoring cache statistics, you gain visibility into cache efficiency and can make data-driven adjustments to:
- Cache size and TTL
- Which entities to cache or evict
- Cache provider configuration
Proper tuning can drastically improve app responsiveness and reduce DB load.