How Does the Flush Mechanism Work in Hibernate
Flush is the process of synchronizing data from the persistence context (Hibernate cache) to the database. Understanding the flush mechanism is critical for transaction manageme...
Overview
Flush is the process of synchronizing data from the persistence context (Hibernate cache) to the database. Understanding the flush mechanism is critical for transaction management and performance optimization.
Junior Level
What is Flush
Flush is the process of writing all changes from memory (persistence context) to the database.
User user = entityManager.find(User.class, 1L);
user.setName("New Name"); // changed in memory
// Flush hasn't happened yet - DB NOT updated!
entityManager.flush(); // explicit flush - UPDATE executed in DB
// or
// On commit - automatic flush
When Flush Happens
- On transaction
commit- automatically - On
entityManager.flush()- explicitly - Before executing a query - to return actual data
@Transactional
public void updateUser() {
User user = entityManager.find(User.class, 1L);
user.setName("New");
// flush hasn't happened yet
// DB still contains old name
// On method exit -> @Transactional commit -> flush
}
Manual Flush Example
@Transactional
public void batchInsert(List<User> users) {
for (int i = 0; i < users.size(); i++) {
entityManager.persist(users.get(i));
if (i % 50 == 0) {
entityManager.flush(); // flush to DB
entityManager.clear(); // clear cache
}
}
}
Middle Level
FlushMode
// AUTO (default) - flush when necessary
entityManager.setFlushMode(FlushModeType.AUTO);
// COMMIT - flush only on commit
entityManager.setFlushMode(FlushModeType.COMMIT);
// ALWAYS - before every query (rarely used)
entityManager.setFlushMode(FlushModeType.ALWAYS);
// (Note: FlushModeType.ALWAYS was deprecated in Hibernate 5 and removed in Hibernate 6. In modern versions, use AUTO or COMMIT.)
FlushMode.AUTO vs COMMIT
// AUTO - flush before query
User user = entityManager.find(User.class, 1L);
user.setName("New");
// Before this query - flush (to return actual data)
List<User> users = entityManager.createQuery("FROM User", User.class)
.getResultList(); // includes "New" user
// COMMIT - flush only on commit
entityManager.setFlushMode(FlushModeType.COMMIT);
user.setName("New");
// This query will NOT see "New" user (flush hasn't happened)
List<User> users = entityManager.createQuery("FROM User", User.class)
.getResultList(); // does NOT include "New" user
Manual Flush for Batch Operations
@Transactional
public void batchUpdate(List<User> users) {
for (int i = 0; i < users.size(); i++) {
entityManager.merge(users.get(i));
if (i % 50 == 0) {
entityManager.flush(); // flush 50 UPDATEs to DB
entityManager.clear(); // clear persistence context
}
}
// Final flush for remaining
entityManager.flush();
entityManager.clear();
}
Common Mistakes
// Frequent flush - slow
for (User user : users) {
entityManager.persist(user);
entityManager.flush(); // every time - very slow!
}
// Periodic flush
for (int i = 0; i < users.size(); i++) {
entityManager.persist(users.get(i));
if (i % 50 == 0) {
entityManager.flush();
entityManager.clear();
}
}
Senior Level
Internal Implementation
Flush process:
1. Dirty checking
- Traverse all entities in persistence context
- Compare snapshot with current state
- For changed ones - schedule UPDATE
2. Generation order
- INSERT first (to get IDs)
- UPDATE next
- DELETE last (to avoid FK violations)
3. SQL generation
- For each scheduled operation
- Generates SQL considering dirty fields
4. Execution
- Executes SQL in DB (JDBC batch)
- Updates snapshot
5. Post-flush
- Updates EntityEntry states
- Resets dirty flags
Order of Operations
On flush, Hibernate follows this order:
1. All entity INSERTs (in persist() order)
2. All entity UPDATEs (in dirty detection order)
3. All collection UPDATEs (for collection changes)
4. All collection DELETEs (for removed elements)
5. All entity DELETEs (in remove() order)
This is important for:
- Foreign key constraints
- Referential integrity
- Identity generation
This order is critical because of foreign key constraints. If Hibernate
tries to INSERT a child before INSERTing the parent, the DB throws FK violation.
Similarly - DELETE parent before DELETE child.
Flush and Optimistic Locking
@Version
private Integer version;
// On flush:
// UPDATE users SET name = ?, version = version + 1
// WHERE id = ? AND version = ?
// If version doesn't match -> OptimisticLockException
Advanced Settings
spring:
jpa:
properties:
hibernate:
# Flush order for different operations
order_inserts: true # group INSERTs
order_updates: true # group UPDATEs
order_deletes: true # group DELETEs
# JDBC batch size
jdbc.batch_size: 50
Flush and Transactions
// @Transactional defines flush boundaries
@Transactional
public void method1() {
user.setName("A");
// flush on commit
}
@Transactional
public void method2() {
user.setName("B");
entityManager.flush(); // explicit flush
// another flush on commit (if there were changes)
}
Best Practices
AUTO flush mode by default
Manual flush for batch operations
flush + clear every 50-100 entities
COMMIT mode when actual data not needed
order_inserts/order_updates for optimization
ALWAYS mode (avoid)
Flush without reason
Without clear after flush in batches
Ignoring operation order
Interview Cheat Sheet
Must know:
- Flush - synchronization of data from persistence context to DB
- Happens on: commit, entityManager.flush(), before query (AUTO mode)
- FlushMode: AUTO (default), COMMIT (only on commit), ALWAYS (deprecated)
- Operation order: INSERT -> UPDATE -> DELETE (for FK constraints)
- For batch: flush + clear every 50-100 entities
- order_inserts/order_updates - SQL grouping for optimization
Frequent follow-up questions:
- AUTO vs COMMIT? AUTO - flush before query (actual data), COMMIT - only on commit
- Why is INSERT->UPDATE->DELETE order important? Foreign key constraints: cannot INSERT child before INSERT parent
- Why is frequent flush slow? Each flush = SQL queries, 1000 entities x flush = 1000 SQL
- What is JDBC batch_size? Groups SQL queries for batch sending, reduces network round trips
Red flags (DO NOT say):
- “Flush after every persist” - very slow, better batch flush
- “ALWAYS mode for all queries” - deprecated, huge overhead
- “Without clear after flush in batches” - persistence context grows, OOM
- “I don’t understand operation order” - can cause FK violation
Related topics:
- [[12. What is Dirty Checking in Hibernate]]
- [[7. Describe the Entity Lifecycle in Hibernate]]
- [[14. What is the Difference Between persist() and merge()]]
- [[17. How to Implement Optimistic Locking in JPA]]