Hibernate onFlushDirty interceptor is called several times with the same values

I have a problem with my HibernateInterceptor. I extend the EmptyInterceptor and override the onFlushDirty method. I use this method to manually check dirty values ​​(comparing previous values ​​with current values) to record audit logs for modified objects. The problem is that in some specific situations it happens that the same object is passed to the onFlushDirty method several times before calling the postFlush method. Previous values ​​and current values ​​do not change from call to call. Thus, my audit trail records the same changes several times. If the property of my object changes (for example, from NEW to IN_PROGRESS ), this change is passed two or more times to onFlushDirty . Why is this happening? This is real weird behavior and is not expected in my opinion.

The onFlushDirty interceptor call is onFlushDirty by the auto-flush Hibernate behavior. When a request is executed during a session, it clears all dirty objects in the session. I expect this to be done only once for a dirty entity, but it seems that the object is still marked as dirty even after a flash. Then another request is executed in the session and again - the object is cleared again. Old values ​​and current values ​​are the same as during the first reset.

I tried to reproduce this problem in test mode, but I could not provoke such multiple resets. I hope you Hibernate specialists can help me before I have to debug all the Hibernate code.

Cheers, Chris

+7
hibernate interceptor
source share
1 answer

After some debugging, I found the reason for the multiple onFlushDirty calls:

As explained above, the flash mode in my application is set to AUTO. Before a request is executed inside a transaction, Hibernate decides whether to hide dirty objects or not. Whatever the outcome of this decision: the onFlushDirty method in the HibernateInterceptor is called for sure for every dirty object in the session, even if it decided not to reset later.

If an object of type A is in a dirty state in a session, and a query for entity type B is executed in this session, Hibernate does not clear the dirty object, because it does not affect the table that the query uses, and therefore a flash is not needed.

If several requests are executed in a session, it may happen that the onFlushDirty method is called several times for the same dirty object, but it never spoils into the database and remains dirty until the current transaction is completed.

Take a look at the Hibernate DefaultAutoFlushEventListener class

 public void onAutoFlush(AutoFlushEvent event) throws HibernateException { ... if ( flushIsReallyNeeded(event, source) ) { log.trace("Need to execute flush"); ... } else { log.trace("Dont need to execute flush"); ... } } 
+7
source share

All Articles