Hibernate Performance
Second-Level Cache in Hibernate
Configure Hibernate's optional SessionFactory-level cache so suitable entity data can be reused across multiple sessions.
What Is the Second-Level Cache?
The second-level cache is shared by sessions created from the same SessionFactory. When an eligible entity is loaded in one session, Hibernate may store its state in a cache region. A later session can reuse that state instead of querying the database.
Enable Second-Level Caching
Second-level caching is not useful until a cache region factory and a cache provider are configured. Hibernate 6 provides the hibernate-jcache integration for JCache-compatible providers.
<dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-jcache</artifactId> <version>6.6.9.Final</version> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.10.8</version> </dependency>
Keep provider versions compatible with the Hibernate and Jakarta dependencies used by the application. Other integrations, such as Infinispan, may be more appropriate for clustered deployments.
<property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">jcache</property> <property name="hibernate.javax.cache.provider"> org.ehcache.jsr107.EhcacheCachingProvider </property> <property name="hibernate.javax.cache.uri">ehcache.xml</property>
Configuration property names vary across Hibernate generations and JCache integrations. Confirm the exact settings for the selected Hibernate version and provider.
Mark an Entity as Cacheable
Enabling the cache does not mean every entity should be cached. Mark suitable entities explicitly and choose a concurrency strategy.
import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Country {
@Id
private Long id;
private String name;
}READ_ONLY suits immutable reference data. For data that changes, select a strategy only after understanding update frequency, concurrency, and consistency requirements.
Cache Concurrency Strategies
| Strategy | Typical use |
|---|---|
READ_ONLY | Immutable data that never changes after deployment. |
NONSTRICT_READ_WRITE | Data that changes rarely and can tolerate a short stale-data window. |
READ_WRITE | Mutable data requiring coordinated cache updates through a supported strategy. |
TRANSACTIONAL | Provider and transaction environment support transactional cache semantics. |
Second-Level Cache Example
The first session loads the entity. After it closes, a second session can use the shared cache when the entity is cacheable and the provider has retained the entry.
try (Session firstSession = factory.openSession()) {
Country first = firstSession.find(Country.class, 1L);
}
try (Session secondSession = factory.openSession()) {
Country second = secondSession.find(Country.class, 1L);
}The second lookup is eligible for a second-level cache hit. The actual result depends on entity cache metadata, cache configuration, expiry, invalidation, and whether the first-level cache already contains the entity.
Cache Regions and Collections
Hibernate organizes cached data into regions. An entity hierarchy has an entity region, while a cached collection has a collection-region name derived from its role.
@OneToMany(mappedBy = "department") @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) private Set<Employee> employees = new HashSet<>();
Cache a collection only when its access pattern and invalidation behavior justify the memory and operational cost. Query-result caching is separate and should not be confused with entity caching.
Evict and Manage Cached Data
Use the Hibernate cache API when an administrative action requires explicit eviction.
SessionFactory sessionFactory = ...;
sessionFactory.getCache()
.evictEntityData(Country.class, 1L);
sessionFactory.getCache()
.evictEntityData(Country.class);
sessionFactory.getCache().evictAllRegions();Eviction APIs are powerful and can affect active application traffic. Prefer correct cache invalidation and provider configuration over frequent manual eviction.
First-Level versus Second-Level Cache
| Characteristic | First-level cache | Second-level cache |
|---|---|---|
| Scope | One Session | Shared by sessions from one SessionFactory |
| Default | Enabled automatically | Requires a provider and explicit entity configuration |
| Data | Managed entity instances | Cached entity state and configured collection data |
| Lifetime | Session or persistence-context lifetime | Provider and region lifetime, subject to expiry and eviction |
| Main benefit | Identity consistency within a unit of work | Reuse across sessions and reduced database reads |
Cache Providers
Hibernate integrates with external cache implementations rather than being a complete cache database itself.
- JCache-compatible providers: use the Hibernate JCache integration with a provider such as Ehcache where appropriate.
- Infinispan: useful for distributed or clustered cache scenarios when its operational model fits the application.
- Other integrations: verify compatibility, maintenance status, clustering behavior, serialization, and transaction support before adoption.
Older tutorials may mention SwarmCache, OSCache, or JBoss Cache. These names describe historical integrations and should not be copied into a current Hibernate configuration without verifying project compatibility.
Second-Level Cache Best Practices
- Cache stable, frequently read data rather than every entity.
- Measure cache hit rate, database load, memory, and stale-data behavior.
- Choose a concurrency strategy that matches the data's consistency requirements.
- Do not cache data that changes outside Hibernate unless invalidation is coordinated.
- Keep cache regions and expiry policies explicit.
- Test updates, deletes, rollbacks, deployment, and cluster behavior.
- Remember that query caching is separate from second-level entity caching.
Reference: Hibernate ORM caching documentation
