Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Hibernate from flushing in list?

Tags:

java

hibernate

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?

like image 323
Konrad Garus Avatar asked Jan 18 '13 16:01

Konrad Garus


People also ask

Does Hibernate flush commit?

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.

What is flushing in Hibernate?

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.

What is the default flush mode in Hibernate?

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.

Why do we use flush in Hibernate?

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.


1 Answers

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:

  1. Select everything you'll need during the session before you make any modifications (ie., re-order things so that all your queries are issued before any modifications are made).
  2. 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);
    
like image 117
Stevie Avatar answered Sep 22 '22 23:09

Stevie