I am using Hibernate 4.3.4 and running into an issue where HQL returns stale data due to the session cache. This problem can be illustrated in the following (simple) scenario:
Code:
Entity: Employee (name PK, emp_type)
name emp_type
John Doe 'C'
Jane Doe 'P'
Start hibernate transaction:
1. Run HQL: "SELECT e FROM Employee e WHERE e.name = 'John Doe'"
2. Run query: "UPDATE employee SET emp_type = 'F' where name = 'John Doe'"
3. Run HQL: "SELECT e FROM Employee e WHERE e.employeeType = 'F'"
This is just a contrived example of the scenario, but illustrates the problem.
- Step 1 hits the database and hydrates an entity for the 'John Doe' employee record.
- Step 2 is simply illustrating some transaction committing a change to the state of the database (and not necessarily in the current Hibernate transaction).
- Step 3 again hits the database and does return the John Doe entity (since it has been updated to emp_type = 'F'); however, calling employee.getType() will return the original 'C' value and not the updated 'F' value. This is due to the session cache returning the entity that was hydrated in step 1. This seems to contradict the documentation here:
http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch11.html
Quote:
However, Hibernate does guarantee that the Query.list(..) will never return stale or incorrect data.
Obviously, I can simply call "refresh" on the entity but that is not a good solution when the HQL actually results in several hundred rows. Is this a bug or is stale data defined differently than I assume?
The most efficient method I can think of to perform a bulk read/refresh is to do something like this:
Code:
Query = ...
List entities = Query.list();
for (Entity entity : entities) {
session.evict(entity);
}
entities = Query.list();
This requires two queries rather than one which is still far better than performing a refresh on several hundred entities. Unfortunately, this has the potential to leave evicted entities associated with existing objects which can obviously cause its own problems.
Anyway, my core questions are - is there something I'm missing here? Would this be considered a bug or is there some switch/hint I can utilize with which to ask Hibernate to rehydrate these cached entities for me?