Hi,
We have been using Transaction.registerSynchronization() to publish updated entities on an external system after the last flush() but before the actual commit() using Synchronization.beforeCompletion().
This worked fine in Hibernate 3, but since Hibernate 4 the order of execution of these two operations has changed and now Synchronization.beforeCompletion() is called BEFORE Session.managedFlush() meaning that we sometimes miss a few updates (the ones triggered during the managed flush).
Related code in H4 JdbcTransaction (sendBeforeTransactionCompletionNotifications happens before managedFlush()) :
Code:
@Override
protected void beforeTransactionCommit() {
transactionCoordinator().sendBeforeTransactionCompletionNotifications( this );
// basically, if we are the driver of the transaction perform a managed flush prior to
// physically committing the transaction
if ( isDriver && !transactionCoordinator().getTransactionContext().isFlushModeNever() ) {
// if an exception occurs during flush, user must call rollback()
transactionCoordinator().getTransactionContext().managedFlush();
}
if ( isDriver ) {
transactionCoordinator().getTransactionContext().beforeTransactionCompletion( this );
}
}
And in H3 / JDBCTransaction (notifySynchronizationsBeforeTransactionCompletion happens after managedFlush) :
Code:
public void commit() throws HibernateException {
if (!begun) {
throw new TransactionException("Transaction not successfully started");
}
log.debug("commit");
if ( !transactionContext.isFlushModeNever() && callback ) {
transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
}
notifySynchronizationsBeforeTransactionCompletion();
if ( callback ) {
jdbcContext.beforeTransactionCompletion( this );
}
Is there any particular reason why this order has changed ?
It looks like this is almost impossible to use together entity listeners and synchronizations in a reliable and useful way.
William