Site icon akquinet AG – Blog

JPA Pitfalls (10): Query Flush Mode

This blog article is part of a “series of blog articles” about common pitfalls using JPA and ways to avoid them. In this article, we describe unexpected results of JPQL queries with respect of the query flush mode.

JPA supports two flush modes when executing a query within a transaction: COMMIT and AUTO.

Employee e = ... // Employee with weekyhours 40
e.setWeeklyhours(41);
q = em.createQuery(
  "SELECT e FROM Employee e WHERE e.weeklyhours > 40");
q.setFlushMode(FlushModeType.COMMIT);
List<Employee> result = q.getResultList();
// result.contains(e) -> false

When executing the query, the employee in the database still has the old value weeklyhours = 40, so the employee is not part of the query result.

It is also possible that the query result includes an entity that does not match the where clause of the JPQL query:

Employee e = ... // Employee with weekyhours 40
e.setWeeklyhours(41);
q = em.createQuery(
  "SELECT e FROM Employee e WHERE e.weeklyhours = 40");
q.setFlushMode(FlushModeType.COMMIT);
List<Employee> result = q.getResultList();
// result.contains(e) -> true, 
// but e does not match the where clause

Again, the employee in the database still has the old value weeklyhours = 40, so this time it is included in the query result. Since the entity is already loaded in the current transaction the query result will include the current version of the employee. But the current version has updated the weeklyhours to 41 which does not match the where clause of the JPQL query.

Recommendation: Use the query optimization flush mode COMMIT only if the modifications in the current transaction do not affect the query result.

You can find an example of this pitfall and its solution in the class QueryFlushModeExperiment in this project: https://github.com/akquinet/jpapitfalls.git.

Exit mobile version