Mastering Hibernate Caching – Part 3: Performance Tuning Using Cache Statistics

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

MetricMeaningDesired Direction
Second Level Cache Hit CountNumber of cache hitsHigh
Second Level Cache Miss CountNumber of cache missesLow
Second Level Cache Put CountNumber of puts to cacheBalanced (depends)
Entity Fetch CountHow often entities are fetched from DBLow (if cache effective)
Query Execution CountNumber of executed queriesLow

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.



Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *