Here is the output I get:
onFlushDirty old:Bill new:John
onFlushDirty old:Bill new:John
Note that the onFlushDirty() method is triggered twice. Once for the commit, but before that if gets triggered once for each call to query.list().
Here's the problem:
query.list() calls
session.findBySQL() which calls
session.autoFlushIfRequired().
autoFlushIfRequired() then calls flushEverything() which triggers the interceptor. However, execute() is never invoked because areTablesToBeUpdated() returns false. So the interceptor is triggered even though the data has not been flushed to the database.
Looking through the hibernate code, I can see that you might need to flush on a call to findBySQL(). This ensures the integrity of the data you read, though you only need to truly flush if the query is reading from a table that you have already updated in the current session - hence the call to areTablesToBeUpdated(). But why is the call to flushEverything() outside the if clause? ie why not do:
Code:
private boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
if ( flushMode==FlushMode.AUTO && dontFlushFromFind==0 ) {
int oldSize = collectionRemovals.size();
//flushEverything();
if ( areTablesToBeUpdated(querySpaces) ) {
log.trace("Need to execute flush");
flushEverything();
execute();
postFlush();
// note: execute() clears all collectionXxxxtion collections
return true;
}
else {....
To work around the problem I need to manually insert calls to session.flush() immediately prior to every query.list(). I could probably also do something with FlushMode.
I hope this proviced enough detail.
thanks,
Mike