Home/Learn/Hibernate & JPA/Hibernate Statistics & Logging

Hibernate Statistics & Logging

Intermediate
Advanced

Enable hibernate.generate_statistics and show_sql to see query counts, cache hit ratios, and connection acquisition time — essential for identifying performance bottlenecks.

Overview

Hibernate Statistics is the built-in profiling tool that tracks per-session and cumulative metrics: query execution count, query execution time, entity load count, collection fetch count (N+1 detector), second-level cache hit/miss ratios, and connection acquisition time. In development, enable show_sql and format_sql to see every query in the console. In production, expose Statistics via Micrometer (Hibernate 6 + Spring Boot 3 auto-configure this) and alert on session query count anomalies. The statistics API is the fastest way to detect N+1 problems, missing indexes, and cache misconfiguration without a profiler.

Enabling SQL logging and statistics in development

show_sql prints every SQL statement to stdout. format_sql pretty-prints multi-line SQL. use_sql_comments adds JPQL comments to the SQL for context. For production-safe logging, use the org.hibernate.SQL logger category at DEBUG level, which routes through SLF4J instead of stdout.

YAML — SQL logging configuration for development and production
# application.yml — development SQL visibility
spring:
  jpa:
    show-sql: true                        # print SQL to stdout (dev only)
    properties:
      hibernate:
        format_sql: true                  # pretty-print SQL
        use_sql_comments: true            # add JPQL context as SQL comments
        generate_statistics: true         # enable statistics collection
        session.events.log.LOG_QUERIES_SLOWER_THAN_MS: 50  # log slow queries

# Production-safe: route through SLF4J (respects log level config)
logging:
  level:
    org.hibernate.SQL: DEBUG              # SQL statements
    org.hibernate.orm.jdbc.bind: TRACE    # bind parameter values
    org.hibernate.stat: DEBUG             # statistics logging

# Example console output with show-sql + format_sql:
# /* select generatedAlias0 from Order as generatedAlias0 */
# select
#     o1_0.id, o1_0.customer_id, o1_0.total
# from
#     orders o1_0
# where
#     o1_0.customer_id=?

Reading Hibernate Statistics programmatically

SessionFactory.getStatistics() exposes a Statistics object with query counts, entity counts, and cache metrics. Log stats per request to detect N+1 at development time: a single API call that executes 100+ queries indicates a fetch strategy problem. The most important counters: getQueryExecutionCount(), getEntityLoadCount(), getCollectionFetchCount(), getSecondLevelCacheHitCount().

Java — per-request statistics interceptor for N+1 detection
// Log session statistics per request — detect N+1 in development
@Component
@Profile("dev")
public class HibernateStatsLogger implements HandlerInterceptor {

    private final SessionFactory sessionFactory;

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
                             Object handler) {
        sessionFactory.getStatistics().clear();   // reset counters for this request
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
                                Object handler, Exception ex) {
        Statistics stats = sessionFactory.getStatistics();
        long queries = stats.getQueryExecutionCount();
        long entityLoads = stats.getEntityLoadCount();
        long collectionFetches = stats.getCollectionFetchCount();
        long cacheHits = stats.getSecondLevelCacheHitCount();
        long cacheMisses = stats.getSecondLevelCacheMissCount();

        if (queries > 10) {
            log.warn("POTENTIAL N+1: {} queries, {} entity loads, {} collection fetches on {} {}",
                queries, entityLoads, collectionFetches, req.getMethod(), req.getRequestURI());
        }
        log.debug("Stats: queries={} entities={} collections={} L2-hits={} L2-misses={}",
            queries, entityLoads, collectionFetches, cacheHits, cacheMisses);
    }
}

Micrometer integration and production metrics

Spring Boot 3 + Hibernate 6 auto-configures Micrometer metrics for Hibernate statistics (hibernate.*). These include query execution times, cache hit rates, and session counts as Prometheus-compatible gauges and counters. Build a Grafana dashboard tracking hibernate.queries.executed rate, hibernate.cache.query.hit.ratio, and hibernate.second.level.cache.hit.ratio to catch regressions before they reach production.

YAML + PromQL — Micrometer Hibernate metrics and alerting
# Spring Boot auto-configures these Hibernate metrics (via Micrometer):
# hibernate.queries.executed          — total query count
# hibernate.queries.failed            — failed query count
# hibernate.query.plan.cache.hit      — query plan cache efficiency
# hibernate.second.level.cache.hit    — L2 cache hits
# hibernate.second.level.cache.miss   — L2 cache misses
# hibernate.sessions.open             — sessions opened
# hibernate.sessions.closed           — sessions closed
# hibernate.connections.obtained      — connection pool acquisitions

# Enable statistics (required for Micrometer Hibernate metrics)
spring:
  jpa:
    properties:
      hibernate:
        generate_statistics: true

# PromQL — alert on high query rate per HTTP request
# (high rate + few HTTP requests = N+1 suspect)
rate(hibernate_queries_executed_total[5m])
  / rate(http_server_requests_seconds_count[5m])
  > 20   # alert if > 20 queries per request on average

# PromQL — L2 cache hit rate (should be > 80% for cached entities)
hibernate_second_level_cache_hit_total /
  (hibernate_second_level_cache_hit_total + hibernate_second_level_cache_miss_total)

Key Points to Remember

  • 1show-sql: true prints SQL to stdout — for production use logging.level.org.hibernate.SQL: DEBUG instead
  • 2hibernate.generate_statistics=true enables the Statistics API and Micrometer metric collection
  • 3getQueryExecutionCount() > expected per request is a reliable N+1 detector in integration tests and dev interceptors
  • 4getCollectionFetchCount() tracks lazy collection initialisations — high counts indicate missing JOIN FETCH or batch fetch
  • 5Spring Boot 3 auto-configures Micrometer Hibernate metrics when generate_statistics=true is set
  • 6Cache hit rate (L2 hits / (hits + misses)) < 80% for entities that should be cached indicates cache misconfiguration

Interview Questions

Sign in to ask Aria
1

How would you detect an N+1 query problem in a Spring Boot application without a profiler?

MediumThoughtworks
2

What is the difference between show-sql and logging.level.org.hibernate.SQL=DEBUG?

EasyWipro
3

What Hibernate statistics counter would you check to verify that second-level cache is working?

MediumAccenture
4

How does Spring Boot 3 expose Hibernate statistics to Prometheus without custom code?

MediumPivotal
5

Write a PromQL expression to detect N+1 problems in production by correlating query count with HTTP request count.

HardNetflix

Ask Aria about Hibernate Statistics & Logging

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…