Blog

JPA flushes before query execution

Tags :
Categories :

JPA Flush caused the misbehavior

Sometimes ago, the development team encounters a strange behavior in JPA. There was a use case that checked uniqueness of a record data by querying the db and checking if it has any result. If no result found, it should update the record. The problem occured when before running this query some objects were attached in the context (for example by finding a record) and some updates were applied on the object before query the db for finding duplicates. JPA logs showed that an UPDATE query was submitted to db before the SELECT search query.  The intent of the designer was checking for uniqueness then updating the record but in this case the record has been updated independent of the result of the SELECT query.

JPA Queries and the Flush Mode

The problem relates to not including the flush behavior of EntityManager in the design. As we know, EntityManager operations like persist, merge, and remove do not cause immediate database changes, instead these operations are postponed until the EntityManager is flushed. The true motivation for doing thing this way is performance optimization and JPA tuning.

Flush Mode

Flush mode has two different modes: AUTO and COMMIT. By default, the JPA flush mode is set to AUTO. That means that the EntityManagers performs a flush operation automatically as needed. For transaction scoped EntityManagers, that will occur at the end of transaction and for application managed or extended scoped EntityManagers, it occurs when the persistence context closed. In other words, if entities with pending changes are used in a query, the persistence provider will flush changes to the database before executing the query.  On the other hand, the COMMIT mode means that the flush occurs just at the end of the transaction when commit occurs.

JPA flushmode in our use-case

In our use-case, that error occurred because the changes were applied on the objects before checking the db for duplication. Better design would be checking the db for duplication then doing the mapping and updating the objects. We applied this design change, without changing the JPA flush mode, the system works properly.

JPA providers and FlushMode

But How we can change flush mode when it is necessary?

  • For a specific query it can be changed using the Query.setFlushMode method.
  • In an EntityManager it can be changed by calling setFlushMode(FlushModeType flushMode) of the EntityManager.
  • In eclipseLink, there is also a persistence unit property named "eclipse.persistance-context.flush-mode" that can be set to COMMIT or AUTO.
  • In OpenJPA, there is a property named FlushBeforeQueries that determines whether or not to flush any changes made in the current transaction to the data base before executing a query.

 

As a final note, changing flush mode from the default value to COMMIT can introduce performance and functionality issues when you don't understand the exact procedures inside JPA.

0 Comments :

Comment

All Categories