Hibernate - Cache Eviction with Example

Last Updated : 27 May, 2026

Cache eviction is the process of removing data from the cache to make space for new or updated data. It is important for maintaining cache performance and ensuring data consistency.

Why Cache Eviction Is Important

Cache eviction plays a critical role in maintaining an efficient caching system:

  • Limited Cache Size: Caches have finite memory; eviction removes outdated data to free space.
  • Avoiding Stale Data: Ensures users always see the latest database values.
  • Improving Performance: Retains only frequently accessed and relevant data.
  • Ensuring Consistency: Synchronizes cache with database updates made outside Hibernate.
  • Managing Dynamic Data: Prevents obsolete values from remaining in cache.

Different Types of Cache Eviction

Cache eviction algorithms define how data is removed from the cache when needed.

  • Time-Based Eviction: Removes cached data after a fixed period (TTL – Time To Live) or a period of inactivity (TTI – Time To Idle), ensuring stale data is cleared automatically.
  • Count-Based Eviction: Evicts items based on access frequency; less frequently accessed items are removed first to prioritize important data.
  • Query Result Eviction: Removes cached query results when they expire or when underlying data changes, ensuring queries return up-to-date results.
  • Cache Region Clearing: Clears all cached data in a specific cache region, useful for bulk updates or manual cache management.

Cache Eviction Strategies in Hibernate

Hibernate’s second-level cache supports multiple eviction strategies per cache region:

  • Least Recently Used (LRU): Removes data that has not been used for the longest time.
  • First-In-First-Out (FIFO): Removes the oldest cached data first.
  • Least Frequently Used (LFU): Removes data that is accessed least frequently.

These strategies help Hibernate maintain efficient caching and ensure fresh data.

Implementation of Cache Eviction in Hibernate

This section demonstrates second-level cache eviction using Hibernate + Ehcache with a complete working example.

Step 1: Create Maven Project

Create a Maven project using your IDE (Eclipse / IntelliJ) or command line.

  • Project Name: HibernateCacheEvictionDemo
  • Packaging: jar
  • Java Version: 8 or above

Step 2: Project Directory Structure

Organize the project into standard Maven folders for entities, utilities, and main classes.

h
Project Structure

Step 3: Add Maven Dependencies (pom.xml)

Add Hibernate, Ehcache, H2 database, and logging dependencies in pom.xml.

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="
           http://maven.apache.org/POM/4.0.0
           http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <!-- ================= BASIC PROJECT INFO ================= -->
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>HibernateCacheEvictionDemo</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>Hibernate Cache Eviction Demo</name>
    <description>Hibernate Second Level Cache Eviction using Ehcache</description>

    <!-- ================= PROPERTIES ================= -->
    <properties>
        <java.version>17</java.version>
        <hibernate.version>5.6.15.Final</hibernate.version>
        <ehcache.version>2.10.9.2</ehcache.version>
        <h2.version>2.2.224</h2.version>
        <jpa.version>2.2</jpa.version>
        <slf4j.version>1.7.36</slf4j.version>
    </properties>

    <!-- ================= DEPENDENCIES ================= -->
    <dependencies>

        <!-- Hibernate Core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <!-- Hibernate Second Level Cache (Ehcache) -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <!-- Ehcache (Hibernate 5 compatible) -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>${ehcache.version}</version>
        </dependency>

        <!-- H2 In-Memory Database -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${h2.version}</version>
            <scope>runtime</scope>
        </dependency>

        <!-- JPA API -->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>${jpa.version}</version>
        </dependency>

        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

    </dependencies>

    <!-- ================= BUILD ================= -->
    <build>
        <plugins>

            <!-- Maven Compiler Plugin (MANDATORY for Java 17) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <release>${java.version}</release>
                </configuration>
            </plugin>

            <!-- Optional: Run Main Class via Maven -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <mainClass>com.example.main.CacheEvictionDemo</mainClass>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

Step 4: Configure Hibernate (hibernate.cfg.xml)

Configure database connection, entity mapping, and enable second-level cache.

XML
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Database Configuration -->
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.url">jdbc:h2:mem:testdb</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.connection.password"></property>

        <!-- Hibernate Properties -->
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>

        <!-- Enable Second Level Cache -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.region.factory_class">
            org.hibernate.cache.ehcache.EhCacheRegionFactory
        </property>

        <mapping class="com.example.entity.Employee"/>

    </session-factory>
</hibernate-configuration>

Step 5: Configure Ehcache (ehcache.xml)

Define cache regions and eviction policies such as LRU, TTL, and max entries.

XML
<ehcache>

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxEntriesLocalHeap="100"
            eternal="false"
            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            overflowToDisk="false"/>

</ehcache>

Step 6: Create Entity Class (Employee.java)

Create a cacheable entity and enable second-level caching using Hibernate annotations.

Java
package com.example.entity;

import javax.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "employee")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {

    @Id
    private int id;

    private String name;

    private double salary;

    public Employee() {}

    public Employee(int id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    // Getters and Setters
}

Step 7: Create Hibernate Utility (HibernateUtil.java)

Create a utility class to initialize and provide a singleton SessionFactory.

Java
package com.example.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory =
            new Configuration().configure().buildSessionFactory();

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Step 8: Create Main Class (CacheEvictionDemo.java)

This class demonstrates cache usage and cache eviction.

Java
package com.example.main;

import com.example.entity.Employee;
import com.example.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class CacheEvictionDemo {

    public static void main(String[] args)
    {

        SessionFactory factory
            = HibernateUtil.getSessionFactory();

        // Save Employee (DB + L2 Cache)
        Session session1 = factory.openSession();
        Transaction tx = session1.beginTransaction();

        session1.save(new Employee(1, "Alice", 50000));

        tx.commit();
        session1.close();

        // First Fetch (L2 Cache Hit OR DB if cache empty)
        Session session2 = factory.openSession();
        Employee e1 = session2.get(Employee.class, 1);
        System.out.println("First Fetch (L2 Cache): "
                           + e1.getName());
        session2.close();

        // Second Fetch (L2 Cache Hit)
        Session session3 = factory.openSession();
        Employee e2 = session3.get(Employee.class, 1);
        System.out.println("Second Fetch (L2 Cache): "
                           + e2.getName());
        session3.close();

        //  Evict Cache
        factory.getCache().evictEntity(Employee.class, 1);
        System.out.println(
            "Cache evicted for Employee ID = 1");

        //  Fetch After Eviction (DB Hit → SQL will appear)
        
        Session session4 = factory.openSession();
        Employee e3 = session4.get(Employee.class, 1);
        System.out.println("Fetch After Eviction (DB Hit): "
                           + e3.getName());
        session4.close();

        factory.close();
    }
}

Step 9: Run the Project

Run the main class and observe console output to verify cache eviction behavior.

Output:

output
Output
Comment