For versioned table, when a thread tries to update the row which is deleted in DB, stale state exception is expected to be thrown, but often it is not worked as expected.
After checking in the code, when merge flow is hit, there is select operation done and when result is null (row is deleted) entityIsTransient is triggered to do an insert operation rather than throwing the exception in case of versioned table.
Code block: org.hibernate.event.internal.DefaultMergeEventListener
if ( result == null ) {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
entityIsTransient( event, copyCache );
}
Issue is seen in 5.6.10. But there is no change in source code even in latest 6.1.4.0 version as well.
Note: If row is present during this check and deleted before update, then, StaleStateException is seen as expected.