Caching is one of the most important concepts in Hibernate that improves performance and reduces database hits. Hibernate provides a first-level cache, which is also known as the Session cache. It is enabled by default and plays a crucial role in ORM performance optimization.
In real-world applications, repeatedly fetching the same entity from the database is wasteful. Instead, Hibernate stores entities in the Session cache, reusing them within the same session. This avoids unnecessary SQL queries and accelerates application performance.
In this tutorial, we will explore Hibernate First-Level Cache, its configuration, usage, pitfalls, and best practices with practical Java examples.
What is First-Level Cache in Hibernate?
- Definition: First-level cache in Hibernate is the cache associated with the
org.hibernate.Session
object. - Scope: Cache is session-scoped (lives only within a Hibernate session).
- Default Behavior: It is enabled by default and cannot be disabled.
- Key Benefit: Reduces redundant database queries by reusing objects stored in the session.
Analogy: Think of the first-level cache like a shopping cart in an online store. As long as you’re logged in (session), you can reuse items already added (fetched objects) without fetching them again from the warehouse (database).
Required Setup
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
</session-factory>
</hibernate-configuration>
Entity Example
import jakarta.persistence.*;
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String course;
// Getters and setters
}
Demonstrating First-Level Cache
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class FirstLevelCacheExample {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
// First fetch - SQL executed
Student student1 = session.get(Student.class, 1L);
System.out.println("First Fetch: " + student1.getName());
// Second fetch - No SQL executed, object retrieved from session cache
Student student2 = session.get(Student.class, 1L);
System.out.println("Second Fetch: " + student2.getName());
tx.commit();
session.close();
factory.close();
}
}
Output:
Hibernate: select student0_.id as id1_0_0_, student0_.course as course2_0_0_, student0_.name as name3_0_0_ from students student0_ where student0_.id=?
First Fetch: John
Second Fetch: John
Notice that Hibernate executes the SQL query only once.
Clearing the Cache
Sometimes you may want to clear the cache explicitly:
session.evict(student1); // Removes specific object from cache
session.clear(); // Clears entire session cache
Real-World Use Cases
- Avoiding duplicate queries: Frequently accessed entities remain in memory.
- Improved performance: Minimizes DB round-trips.
- Entity lifecycle management: Entities remain attached to the session, supporting dirty checking and auto-update.
Common Pitfalls and Anti-Patterns
- Misunderstanding scope: Cache is limited to a single session. A new session = a fresh cache.
- Memory issues: Large session cache can consume too much memory if not managed.
- Improper session usage: Keeping sessions open too long leads to stale data and memory leaks.
Best Practices
- Use short-lived sessions.
- Always close sessions properly.
- Evict unused objects to free memory.
- Do not rely solely on first-level cache for performance in enterprise apps — combine with second-level cache when needed.
📌 Hibernate Version Notes
- Hibernate 5:
- Uses
javax.persistence
package. - SessionFactory setup with
hibernate.cfg.xml
.
- Uses
- Hibernate 6:
- Migrated to
jakarta.persistence
. - Enhanced SQL support and query APIs.
- Better integration with modern frameworks like Spring Boot 3.
- Migrated to
Conclusion and Key Takeaways
- Hibernate First-Level Cache is always enabled and tied to the Session.
- It reduces database round-trips by reusing cached objects.
- Use it carefully to avoid memory bloat and stale data issues.
- It is best suited for short-lived session transactions and works seamlessly with Hibernate’s dirty checking.
FAQ
Q1. What’s the difference between Hibernate and JPA?
Hibernate is an implementation of JPA (specification). JPA provides the API, Hibernate provides the actual ORM engine.
Q2. How does Hibernate caching improve performance?
By reducing database calls through storing frequently accessed data in memory.
Q3. What are the drawbacks of eager fetching?
It loads unnecessary data upfront, leading to memory overhead and performance slowdown.
Q4. How do I solve the N+1 select problem in Hibernate?
Use fetch join
, batch fetching, or second-level cache to optimize queries.
Q5. Can I use Hibernate without Spring?
Yes, Hibernate can be used standalone with its own configuration.
Q6. What’s the best strategy for inheritance mapping?
It depends on use case: SINGLE_TABLE
(performance), JOINED
(normalization), TABLE_PER_CLASS
(rarely used).
Q7. How does Hibernate handle composite keys?
Using @Embeddable
and @EmbeddedId
annotations.
Q8. How is Hibernate 6 different from Hibernate 5?
Hibernate 6 uses jakarta.persistence
namespace and improved query APIs.
Q9. Is Hibernate suitable for microservices?
Yes, but lightweight alternatives like JOOQ or MyBatis may be more efficient in some cases.
Q10. When should I not use Hibernate?
When you need fine-grained control over SQL queries or extremely high-performance batch operations.