Hibernate Dirty Checking and Flushing Mechanism Explained

Illustration for Hibernate Dirty Checking and Flushing Mechanism Explained
By Last updated:

One of Hibernate’s biggest strengths as an ORM is its ability to automatically detect changes made to entities and persist them to the database. This powerful behavior is enabled by two core concepts: Dirty Checking and the Flushing Mechanism.

Think of dirty checking as a personal assistant who remembers every edit you make to a draft document. Flushing is like pressing “Save” to sync your edits with the central server. Together, they make Hibernate both intelligent and efficient in handling persistence.

In this tutorial, we’ll cover how Hibernate manages dirty checking and flushing, their real-world importance, configurations, pitfalls, and best practices.


What is Dirty Checking in Hibernate?

Dirty checking is Hibernate’s ability to automatically detect changes in persistent entities and synchronize them with the database when a transaction is committed or the session is flushed.

Example

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Employee emp = session.get(Employee.class, 1L);
emp.setSalary(emp.getSalary() + 1000); // Change tracked automatically

tx.commit(); // Hibernate detects change and issues UPDATE query
session.close();

You don’t explicitly call session.update(emp) here. Hibernate detects the change using dirty checking and updates the row.


How Hibernate Performs Dirty Checking

  1. When an entity is loaded, Hibernate keeps a snapshot of its initial state.
  2. When a transaction is committed or flushed, Hibernate compares the current state with the snapshot.
  3. If differences exist, an UPDATE SQL statement is generated.

What is Flushing in Hibernate?

Flushing is the process of synchronizing the in-memory state of the persistence context with the database.

Important: Flushing does not mean committing.

  • Flush = Hibernate issues SQL to sync changes.
  • Commit = Database transaction is permanently saved.

Example

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Employee emp = new Employee("John", "IT", 5000);
session.save(emp); // Insert queued

session.flush(); // SQL INSERT executed immediately

tx.commit();
session.close();

Here, flush() forces Hibernate to issue SQL before commit.


Flush Modes in Hibernate

Hibernate allows control over flushing behavior via FlushMode.

1. AUTO (Default)

Flush occurs automatically before query execution and transaction commit.

session.setFlushMode(FlushMode.AUTO);

2. COMMIT

Flush only at transaction commit.

session.setFlushMode(FlushMode.COMMIT);

3. ALWAYS

Flush before every query execution.

session.setFlushMode(FlushMode.ALWAYS);

4. MANUAL

Flush happens only when explicitly called.

session.setFlushMode(FlushMode.MANUAL);
session.flush();

Step-by-Step CRUD Example with Dirty Checking and Flushing

Create

Employee emp = new Employee("Alice", "HR", 6000);
session.save(emp); // INSERT queued

Read

Employee emp = session.get(Employee.class, 1L);
System.out.println(emp.getName());

Update

Employee emp = session.get(Employee.class, 1L);
emp.setDepartment("Finance"); // Dirty checking will trigger UPDATE

Delete

Employee emp = session.get(Employee.class, 2L);
session.delete(emp); // DELETE issued at flush/commit

Real-World Use Case: Spring Boot + Hibernate

spring:
  jpa:
    properties:
      hibernate:
        flushMode: AUTO
    hibernate:
      ddl-auto: update

With Spring Data JPA repositories, dirty checking ensures updated entities are persisted automatically without explicit save calls.


Common Pitfalls & Anti-Patterns

  1. Forgetting that Flush != Commit
    Developers often confuse flushing with committing.

  2. Unnecessary Updates
    Modifying entities without actual value change still triggers updates.

  3. Manual Flush in Wrong Place
    Excessive manual flush calls lead to performance degradation.

  4. Large Transactions
    Dirty checking compares all entities in the persistence context, leading to memory overhead.


Best Practices

  • Use default AUTO flush mode for most cases.
  • Keep transactions short and focused.
  • Avoid unnecessary field modifications.
  • Explicitly call flush() only when needed (e.g., batch inserts).
  • Monitor SQL logs to detect redundant updates.

📌 Hibernate Version Notes

Hibernate 5.x

  • Uses javax.persistence.
  • Default flush mode = AUTO.
  • Dirty checking relies on entity snapshots.

Hibernate 6.x

  • Migrated to jakarta.persistence.
  • Improved dirty checking with better bytecode enhancement.
  • Enhanced support for batch flushing and query plan caching.

Conclusion & Key Takeaways

  • Dirty Checking: Detects entity changes automatically.
  • Flushing: Synchronizes persistence context with the database.
  • Both are essential for Hibernate’s ORM magic.
  • Always distinguish between flush and commit.
  • Optimize transactions and avoid redundant flushes for better performance.

FAQ: Expert-Level Questions

Q1: What’s the difference between Hibernate and JPA?
Hibernate is a JPA implementation that provides extra features like dirty checking and caching.

Q2: How does Hibernate caching improve performance?
It reduces database calls by storing frequently accessed data in memory.

Q3: What are the drawbacks of eager fetching?
It loads unnecessary data, slowing queries and using more memory.

Q4: How do I solve the N+1 select problem in Hibernate?
Use fetch joins, @BatchSize, or entity graphs.

Q5: Can I use Hibernate without Spring?
Yes, Hibernate can work standalone with SessionFactory.

Q6: What’s the best strategy for inheritance mapping?
Depends on use case: SINGLE_TABLE, JOINED, or TABLE_PER_CLASS.

Q7: How does Hibernate handle composite keys?
Using @Embeddable with @EmbeddedId or @IdClass.

Q8: How is Hibernate 6 different from Hibernate 5?
Hibernate 6 uses jakarta.persistence, improves dirty checking, and enhances flushing performance.

Q9: Is Hibernate suitable for microservices?
Yes, but smaller ORMs like jOOQ or MyBatis may suit lightweight services better.

Q10: When should I not use Hibernate?
Avoid Hibernate when low-level SQL control and raw performance are required (e.g., analytics-heavy apps).