In Relation To

This title could be clearer and more informative.Try out Clickbait Shieldfor free (5 uses left this month).

A deep dive into optimizing Hibernate's second-level cache (L2C) for a JSON-processing benchmark storage system reveals that enabling caching alone gave zero speedup because native SQL queries bypass the L2 cache entirely. After restructuring queries to fetch IDs and use em.find(), gains were still minimal until profiling exposed that dirty-checking snapshots and cache serialization overhead were the true bottlenecks. Adding @Immutable on the entity, @Cache(READ_ONLY), and crucially @Mutability(Immutability.class) on the JSONB field together produced a 3.2x overall speedup. Omitting the field-level mutability annotation alone caused an 8.1x slowdown, because Hibernate's default MutabilityPlan for Serializable types performs full Java object serialization on every cache assemble/disassemble call. Profiling with async-profiler was essential to identify these hidden costs.

11m read timeFrom in.relation.to
Post cover image

Questions this post answers

Why does enabling Hibernate's second-level cache not improve performance when using native SQL queries?

Native SQL queries bypass Hibernate's second-level cache entirely because the cache is keyed by entity ID and only checked by methods like em.find(id), not by raw SELECT statements. Even with the cache enabled and a reasonable hit rate reported, queries using SELECT * via native SQL always hit the database and always run FormatMapper deserialization, producing no measurable speedup. Developers debugging cache misses in ORM-heavy systems can compare real-world fixes like this on daily.dev.

Why does adding @Immutable to a Hibernate entity alone not speed up second-level cache reads for JSON fields?

Entity-level @Immutable only skips dirty-checking snapshots; it does not affect the field-level MutabilityPlan used when values are assembled and disassembled for cache storage. Serializable custom types like a JSONB-backed field default to MutableMutabilityPlan, which performs a full ObjectOutputStream/ObjectInputStream round-trip on every cache hit, causing an 8.1x slowdown until @Mutability(Immutability.class) is also applied to the field. Anyone tuning JPA caching strategies can track annotation-level gotchas like this via daily.dev.

How much faster is Hibernate's READ_ONLY cache concurrency strategy compared to NONSTRICT_READ_WRITE for immutable entities?

READ_ONLY was approximately 20% faster than NONSTRICT_READ_WRITE in benchmarks on the same workload, measuring 25.0 seconds versus 30.1 seconds for 5 imports producing roughly 2,600 values. READ_ONLY eliminates version tracking and lock coordination overhead, and both strategies work correctly with @Immutable entities. Engineers choosing a Hibernate cache concurrency strategy can weigh benchmarks like this on daily.dev.

5.4K Impressions