Ok, I have some more information and a new approach. I turned out that the code in the previous post was not problematic. The dirty check does clear some of the internal queues (including the update queue) before returning. Thus, the commit() never sends an update for the evicted entity.
I have been trying to implement something based on the code in the SessionImpl class. It is a rather ugly cut-and-paste of what I think is the relevant parts of the Session.isDirty() method. I may be missing a lot but so far it seems to be working.
Code:
public boolean isDirty(Session s, Object entity)
{
// We need a lot of functionality in SessionImpl
SessionImpl session = (SessionImpl)s;
boolean dirty = false;
// From DefaultDirtyCheckEventListener.onDirtyCheck()
int oldSize = session.getActionQueue().numberOfCollectionRemovals();
try
{
// From AbstractFlushingEventListener.flushEntities()
FlushEntityEventListener[] flushEntityEventListener =
session.getListeners().getFlushEntityEventListeners();
EntityEntry entry = session.getPersistenceContext().getEntry(entity);
FlushEntityEvent entityEvent = new FlushEntityEvent(session, entity, entry );
for (int i = 0; i < flushEntityEventListener.length; i++)
{
flushEntityEventListener[i].onFlushEntity(entityEvent);
}
// From DefaultDirtyCheckEventListener.onDirtyCheck()
dirty = session.getActionQueue().hasAnyQueuedActions();
}
finally
{
// From DefaultDirtyCheckEventListener.onDirtyCheck()
session.getActionQueue().clearFromFlushNeededCheck(oldSize);
}
return dirty;
}
The code seems to work with at least simple cases. It needs to be polished up a lot. Among other things:
* Define Session.isDirty(Object) and implement in SessionImpl
* Maybe introduce DirtyCheckEntityEvent and DirtyCheckEntityEventListener interfaces to make the design similar to a flush that uses FlushEvent/FlushEventListener and FlushEntityEvent/FlushEntityEventListener.
* Check what happens when only collections are dirty. There seems to be other tracks in the flush event handling that handles this.