पाठ 6 / 25
Flushing, the First-Level Cache and Transactions
Explain when Hibernate sends SQL to the database and how transactions bound the persistence context.
When does SQL actually run?
Hibernate does not execute SQL immediately for every change. It queues inserts, updates and deletes and sends them at flush time. With the default FlushModeType.AUTO, a flush happens before transaction commit and before queries whose results could be affected by pending changes, so queries see your own changes. You can flush explicitly with em.flush(), for example to trigger constraint violations early; the transaction can still roll back afterwards. In Spring, the persistence context is usually scoped to the transaction: it opens when a @Transactional method starts and closes when it ends, after which loaded entities are detached. All work in one transaction shares one first-level cache, so loading thousands of entities in one long transaction keeps them all in memory with their snapshots; for batch jobs, periodically flush and clear to keep memory bounded. Reads should also run in transactions, often with @Transactional(readOnly = true), which lets Hibernate skip dirty-checking snapshots and lets some databases optimise.
Batch processing with periodic flush and clear
Keeps the persistence context small while importing many rows.
@Transactional
public void importProducts(List<ProductCsvRow> rows) {
int i = 0;
for (ProductCsvRow row : rows) {
em.persist(new Product(row.sku(), row.title(), row.price()));
if (++i % 50 == 0) { // match hibernate.jdbc.batch_size
em.flush(); // send queued INSERTs as a JDBC batch
em.clear(); // detach everything: free memory and snapshots
}
}
}
@Transactional(readOnly = true)
public List<Product> cheapProducts(BigDecimal max) {
return em.createQuery("select p from Product p where p.price <= :max", Product.class)
.setParameter("max", max)
.getResultList(); // no dirty-check snapshots needed
}A flush is not a commit
em.flush() sends SQL to the database inside the current transaction; the changes are still invisible to other transactions and can be rolled back. Commit is what makes them permanent.
त्वरित जाँच: With the default flush mode, when does Hibernate flush pending changes?
- Before commit and before queries that may be affected by the pending changes
- Only when the application shuts down
- After every setter call
- Never, unless flush() is called
Answer
Before commit and before queries that may be affected by the pending changes — FlushModeType.AUTO flushes before commit and before relevant queries.