How to override the default Hibernate Session FlushMode
Are you struggling with performance issues in your Spring, Jakarta EE, or Java EE application?
What if there were a tool that could automatically detect what caused performance issues in your JPA and Hibernate data access layer?
Wouldn’t it be awesome to have such a tool to watch your application and prevent performance issues during development, long before they affect production systems?
Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, Micronaut, or Play Framework.
So, rather than fixing performance issues in your production system on a Saturday night, you are better off using Hypersistence Optimizer to help you prevent those issues so that you can spend your time on the things that you love!
Introduction
In this article, we are going to see how we can override the default FlushMode used by Hibernate.
If you bootstrap Hibernate natively, and not as a JPA provider, the default Hibernate FlushMode.AUTO strategy will be used, which, as explained in this article, does not trigger a Persistence Context flush prior to executing a native SQL query.
How to override the default Hibernate Session FlushMode@vlad_mihalcea https://t.co/7II0qm0eDv pic.twitter.com/eAijTH25l0
— Java (@java) July 18, 2019
Hibernate default FlushMode AUTO
Assuming we have no Post entity in our database:
assertEquals(
0,
((Number)
entityManager.createQuery("""
select count(p)
from Post p
""")
.getSingleResult()
).intValue()
);
If we persist a Post entity:
entityManager.persist(
new Post()
.setTitle(
"High-Performance Java Persistence"
)
);
and we bootstrap Hibernate natively using the SessionFactoryBuilder, then the default FlushMode.AUTO will not trigger a Persistence Context flush when a native SQL query is executed:
assertEquals(
0,
((Number)
entityManager.createNativeQuery("""
select count(*)
from post
""")
.getSingleResult()
).intValue()
);
This behavior only happens if Hibernate is bootstrap using the SessionFactory class. We can see that flush is delayed until the Hibernate transaction is about to commit:
CALL NEXT VALUE FOR
hibernate_sequence
SELECT
COUNT(*)
FROM
post
-- o.h.e.t.i.TransactionImpl - committing
INSERT INTO post (
title,
id
)
VALUES (
'High-Performance Java Persistence',
1
)
When using JPA, the Persistence Context is flushed on every query execution, be it JPQL, Criteria API or a native SQL query.
How to manually override the default Hibernate Session FlushMode
You can override the default FlushMode either at the Query or Session level.
If you are only interested in changing the FlushMode only for the duration of the currently executing query, then you can do that as illustrated in the following example:
assertEquals(
1,
((Number)
entityManager.createNativeQuery("""
select count(*)
from post
"""
)
.unwrap(org.hibernate.query.Query.class)
.setHibernateFlushMode(FlushMode.ALWAYS)
.getSingleResult()
).intValue()
);
The
FlushMode.ALWAYSmode instructs Hibernate to behave just like the JPAFlushModeType.AUTOmode, therefore, triggering a Persistence Context flush prior to any query, be it JPQL, Criteria API or a native SQL query.
If you want to override the FlushMode for every query executed by the current Hibernate Session, then you can change the FlushMode as follows:
entityManager.unwrap(Session.class)
.setHibernateFlushMode(FlushMode.ALWAYS);
However, this would require you to manually set the FlushMode.ALWAYS for every Session, which is not very convenient for the application developer.
How to automatically override the default Hibernate Session FlushMode
You can define a specific FlushMode at the Hibernate configuration level using the org.hibernate.flushMode configuration property:
spring.jpa.properties.org.hibernate.flushMode=ALWAYS
This way, every Session will use the ALWAYS flush strategy, so we don’t need to manually override the default AUTO flush mode at the Query or Session level.
If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.
Conclusion
Setting the FlushMode.ALWAYS strategy is desirable when bootstrapping Hibernate natively either via the Spring LocalSessionFactoryBean or the Hibernate BootstrapServiceRegistryBuilder.
This way, you provide read-your-writes consistency guarantee, and native SQL queries will include any pending modifications that were scheduled to be executed at flush time.






