I have a simple Hibernate query like:
from MyEntity where name = ?
Nothing fancy, but it's called many times in a fairly big transaction (lasts one second, may load dozens or hundreds of entities). Profiler shows that a lot of time is spent in:
org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1185)
org.hibernate.internal.SessionImpl.list(SessionImpl.java:1240)
org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
In other words - flushing changes before running the actual query.
Can I somehow prevent Hibernate from doing this flush at all?
If not, what can I do to make it faster?
By default, Hibernate uses the AUTO flush mode which triggers a flush in the following circumstances: prior to committing a Transaction. prior to executing a JPQL/HQL query that overlaps with the queued entity actions. before executing any native SQL query that has no registered synchronization.
Flushing is the process of synchronizing the state of the persistence context with the underlying database. The EntityManager and the Hibernate Session expose a set of methods, through which the application developer can change the persistent state of an entity.
AUTO. The Session is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode.
Flushing the session forces Hibernate to synchronize the in-memory state of the Session with the database (i.e. to write changes to the database). By default, Hibernate will flush changes automatically for you: before some query executions. when a transaction is committed.
By default hibernate flushes before issuing a query during a session (FlushMode.AUTO), and chews up lots of CPU time doing it. It is particularly painful if you have a session where many queries and updates run alternately.
If the query is likely to select back data that you have inserted/updated/deleted during the current session then you need these flushes. This may also be the case even if you haven't modified anything in the current transaction but are using a transaction-isolation level like read-uncommitted.
Assuming you don't want uncommitted reads, etc., there are two ways around this that I know of:
If you know for sure that you are selecting data that has not been modified in this session then you can explicitly set the flush-mode to something which won't trigger the flush, like this:
Query query = session.getNamedQuery(SOME_QUERY_NAME);
query.setFlushMode(FlushMode.COMMIT);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With