Tutorials Logic, IN info@tutorialslogic.com

Hibernate Caching First Level, Second Level, EHCache

Hibernate Cache Levels

Hibernate provides two levels of caching to improve performance by reducing database queries:

Cache Level Scope Default Description
First-Level Cache (L1) Session Always enabled Per-session cache. Entities loaded in a session are cached for the session's lifetime.
Second-Level Cache (L2) SessionFactory Disabled Shared across sessions. Requires a cache provider (EHCache, Infinispan, etc.).
Query Cache SessionFactory Disabled Caches query results. Works with L2 cache.

First-Level Cache Demo

First-Level Cache Demo
Session session = sessionFactory.openSession();

// First get: hits the database
User user1 = session.get(User.class, 1L);
System.out.println("First get: " + user1.getUsername()); // SQL executed

// Second get: served from L1 cache (same session)
User user2 = session.get(User.class, 1L);
System.out.println("Second get: " + user2.getUsername()); // NO SQL - from cache

// Same object reference
System.out.println(user1 == user2); // true

// Clear L1 cache
session.evict(user1);  // Remove specific entity from cache
// session.clear();    // Clear entire L1 cache

// After evict: hits database again
User user3 = session.get(User.class, 1L);
System.out.println("After evict: " + user3.getUsername()); // SQL executed again

session.close();
// L1 cache is destroyed when session closes

Second-Level Cache with EHCache

L2 Cache Configuration

L2 Cache Configuration
<!-- Enable L2 cache in hibernate.cfg.xml -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.region.factory_class">
    org.hibernate.cache.jcache.JCacheRegionFactory
</property>

<!-- pom.xml dependency -->
<!--
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-jcache</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.10.8</version>
</dependency>
-->

Second-Level Cache with EHCache - Java Example

Second-Level Cache with EHCache - Java Example
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

// Cache strategies:
// READ_ONLY: For data that never changes (best performance)
// READ_WRITE: For data that changes occasionally (uses soft locks)
// NONSTRICT_READ_WRITE: No strict locking (slight risk of stale data)
// TRANSACTIONAL: Full transactional cache (JTA required)

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;
}

// Cache a collection
@Entity
public class User {
    @OneToMany(mappedBy = "user")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    private List<Order> orders;
}

// Using query cache
Session session = sessionFactory.openSession();
List<Product> products = session.createQuery("FROM Product", Product.class)
        .setCacheable(true)           // Enable query cache
        .setCacheRegion("productCache") // Optional: named cache region
        .list();
session.close();

Cache Scope, Invalidation, and Stale Reads

Hibernate caching changes when a read reaches the database. First-level state belongs to one Session, while second-level regions may be shared across Sessions and requests.

A hit is valuable only when reused data is still valid. Define region scope, concurrency strategy, eviction, and invalidation before enabling query caching or caching frequently updated entities.

  • First-level cache lives inside a Session.
  • Second-level cache is shared across Sessions.
  • Use read-only caching for reference data.
  • Avoid query cache until invalidation behavior is understood.
  • Measure hit rate and stale-read risk together.
Before you move on

Hibernate Caching First Level, Second Level, EHCache Mastery Check

5 checks
  • First-Level Cache (L1) is the session operator; Always enabled produces Per-session cache.
  • Entities loaded in a session are cached for the session's lifetime.
  • Second-Level Cache (L2) is the sessionfactory operator; Disabled produces Shared across sessions.
  • Requires a cache provider (EHCache, Infinispan, etc.).
  • Query Cache is the sessionfactory operator; Disabled produces Caches query results.

Hibernate Questions Learners Ask

The query may not be cacheable, the entity region may have expired, the data may have been invalidated, or the lookup may require association rows that are not cached. The first-level cache is Session-scoped; the second-level cache stores eligible entity state across Sessions.

Avoid aggressively caching highly volatile rows, security-sensitive decisions, inventory values, or data updated outside Hibernate unless invalidation is reliable. Caching works best for frequently read, relatively stable reference data.

Bulk HQL operates directly in the database and bypasses normal per-entity dirty checking. Managed objects already loaded in the Session can still contain old values, and caches may need invalidation. Clear or refresh the persistence context after bulk operations and understand the cache provider’s invalidation behavior before mixing bulk updates with cached entities.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.