HHH-16939 Optimistic and Pessimistic Force Increment Update Statements are not committed when using a batch
This commit is contained in:
parent
58d50e26f7
commit
c7ed34d159
|
@ -48,7 +48,7 @@ public class PessimisticForceIncrementLockingStrategy implements LockingStrategy
|
|||
}
|
||||
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( object );
|
||||
final EntityPersister persister = entry.getPersister();
|
||||
final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
|
||||
final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), false, session );
|
||||
entry.forceLocked( object, nextVersion );
|
||||
}
|
||||
|
||||
|
|
|
@ -542,6 +542,8 @@ public class ActionQueue {
|
|||
// Execute completion actions only in transaction owner (aka parent session).
|
||||
if ( beforeTransactionProcesses != null ) {
|
||||
beforeTransactionProcesses.beforeTransactionCompletion();
|
||||
// `beforeTransactionCompletion()` can have added batch operations (e.g. to increment entity version)
|
||||
session.getJdbcCoordinator().executeBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public class DefaultPostLoadEventListener implements PostLoadEventListener, Call
|
|||
switch ( entry.getLockMode() ) {
|
||||
case PESSIMISTIC_FORCE_INCREMENT:
|
||||
final Object nextVersion = entry.getPersister()
|
||||
.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
|
||||
.forceVersionIncrement( entry.getId(), entry.getVersion(), false, session );
|
||||
entry.forceLocked( entity, nextVersion );
|
||||
break;
|
||||
case OPTIMISTIC_FORCE_INCREMENT:
|
||||
|
|
|
@ -86,7 +86,7 @@ public class LoaderHelper {
|
|||
if ( persister.isVersioned() && requestedLockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT ) {
|
||||
// todo : should we check the current isolation mode explicitly?
|
||||
Object nextVersion = persister.forceVersionIncrement(
|
||||
entry.getId(), entry.getVersion(), session
|
||||
entry.getId(), entry.getVersion(), false, session
|
||||
);
|
||||
entry.forceLocked( object, nextVersion );
|
||||
}
|
||||
|
|
|
@ -2004,32 +2004,7 @@ public abstract class AbstractEntityPersister
|
|||
return superMappingType.getEntityPersister().forceVersionIncrement( id, currentVersion, session );
|
||||
}
|
||||
|
||||
if ( !isVersioned() ) {
|
||||
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
|
||||
}
|
||||
|
||||
if ( isVersionGeneratedOnExecution() ) {
|
||||
// the difficulty here is exactly what we update in order to
|
||||
// force the version to be incremented in the db...
|
||||
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
|
||||
|
||||
}
|
||||
|
||||
final EntityVersionMapping versionMapping = getVersionMapping();
|
||||
final Object nextVersion = getVersionJavaType().next(
|
||||
currentVersion,
|
||||
versionMapping.getLength(),
|
||||
versionMapping.getPrecision(),
|
||||
versionMapping.getScale(),
|
||||
session
|
||||
);
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace(
|
||||
"Forcing version increment [" + infoString( this, id, getFactory() ) + "; "
|
||||
+ getVersionType().toLoggableString( currentVersion, getFactory() ) + " -> "
|
||||
+ getVersionType().toLoggableString( nextVersion, getFactory() ) + "]"
|
||||
);
|
||||
}
|
||||
final Object nextVersion = calculateNextVersion( id, currentVersion, session );
|
||||
|
||||
updateCoordinator.forceVersionIncrement( id, currentVersion, nextVersion, session );
|
||||
|
||||
|
@ -2067,7 +2042,53 @@ public abstract class AbstractEntityPersister
|
|||
return nextVersion;
|
||||
}
|
||||
|
||||
// private String generateVersionIncrementUpdateString() {
|
||||
@Override
|
||||
public Object forceVersionIncrement(
|
||||
Object id,
|
||||
Object currentVersion,
|
||||
boolean batching,
|
||||
SharedSessionContractImplementor session) throws HibernateException {
|
||||
if ( superMappingType != null ) {
|
||||
return superMappingType.getEntityPersister().forceVersionIncrement( id, currentVersion, session );
|
||||
}
|
||||
|
||||
final Object nextVersion = calculateNextVersion( id, currentVersion, session );
|
||||
|
||||
updateCoordinator.forceVersionIncrement( id, currentVersion, nextVersion, batching, session );
|
||||
return nextVersion;
|
||||
}
|
||||
|
||||
private Object calculateNextVersion(Object id, Object currentVersion, SharedSessionContractImplementor session) {
|
||||
if ( !isVersioned() ) {
|
||||
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
|
||||
}
|
||||
|
||||
if ( isVersionGeneratedOnExecution() ) {
|
||||
// the difficulty here is exactly what we update in order to
|
||||
// force the version to be incremented in the db...
|
||||
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
|
||||
|
||||
}
|
||||
|
||||
final EntityVersionMapping versionMapping = getVersionMapping();
|
||||
final Object nextVersion = getVersionJavaType().next(
|
||||
currentVersion,
|
||||
versionMapping.getLength(),
|
||||
versionMapping.getPrecision(),
|
||||
versionMapping.getScale(),
|
||||
session
|
||||
);
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace(
|
||||
"Forcing version increment [" + infoString( this, id, getFactory() ) + "; "
|
||||
+ getVersionType().toLoggableString( currentVersion, getFactory() ) + " -> "
|
||||
+ getVersionType().toLoggableString( nextVersion, getFactory() ) + "]"
|
||||
);
|
||||
}
|
||||
return nextVersion;
|
||||
}
|
||||
|
||||
// private String generateVersionIncrementUpdateString() {
|
||||
// final Update update = new Update( getFactory().getJdbcServices().getDialect() ).setTableName( getTableName( 0 ) );
|
||||
// if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {
|
||||
// update.setComment( "forced version increment" );
|
||||
|
|
|
@ -807,6 +807,14 @@ public interface EntityPersister extends EntityMappingType, RootTableGroupProduc
|
|||
|
||||
Object forceVersionIncrement(Object id, Object currentVersion, SharedSessionContractImplementor session) throws HibernateException;
|
||||
|
||||
default Object forceVersionIncrement(
|
||||
Object id,
|
||||
Object currentVersion,
|
||||
boolean batching,
|
||||
SharedSessionContractImplementor session) throws HibernateException {
|
||||
return forceVersionIncrement( id, currentVersion, session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the class actually been bytecode instrumented?
|
||||
*/
|
||||
|
|
|
@ -37,4 +37,13 @@ public interface UpdateCoordinator {
|
|||
Object currentVersion,
|
||||
Object nextVersion,
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
default void forceVersionIncrement(
|
||||
Object id,
|
||||
Object currentVersion,
|
||||
Object nextVersion,
|
||||
boolean batching,
|
||||
SharedSessionContractImplementor session){
|
||||
forceVersionIncrement( id, currentVersion, nextVersion, session );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,6 +153,19 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
doVersionUpdate( null, id, nextVersion, currentVersion, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceVersionIncrement(
|
||||
Object id,
|
||||
Object currentVersion,
|
||||
Object nextVersion,
|
||||
boolean batching,
|
||||
SharedSessionContractImplementor session) {
|
||||
if ( versionUpdateGroup == null ) {
|
||||
throw new HibernateException( "Cannot force version increment relative to sub-type; use the root type" );
|
||||
}
|
||||
doVersionUpdate( null, id, nextVersion, currentVersion, batching, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void coordinateUpdate(
|
||||
Object entity,
|
||||
|
@ -466,11 +479,21 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
Object version,
|
||||
Object oldVersion,
|
||||
SharedSessionContractImplementor session) {
|
||||
doVersionUpdate( entity, id, version, oldVersion, true, session );
|
||||
}
|
||||
|
||||
protected void doVersionUpdate(
|
||||
Object entity,
|
||||
Object id,
|
||||
Object version,
|
||||
Object oldVersion,
|
||||
boolean batching,
|
||||
SharedSessionContractImplementor session) {
|
||||
assert versionUpdateGroup != null;
|
||||
|
||||
final EntityTableMapping mutatingTableDetails = (EntityTableMapping) versionUpdateGroup.getSingleOperation().getTableDetails();
|
||||
|
||||
final MutationExecutor mutationExecutor = updateVersionExecutor( session, versionUpdateGroup, false );
|
||||
final MutationExecutor mutationExecutor = updateVersionExecutor( session, versionUpdateGroup, false, batching );
|
||||
|
||||
final EntityVersionMapping versionMapping = entityPersister().getVersionMapping();
|
||||
|
||||
|
@ -1001,6 +1024,18 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
.createExecutor( resolveUpdateVersionBatchKeyAccess( dynamicUpdate, session ), group, session );
|
||||
}
|
||||
|
||||
private MutationExecutor updateVersionExecutor(
|
||||
SharedSessionContractImplementor session,
|
||||
MutationOperationGroup group,
|
||||
boolean dynamicUpdate,
|
||||
boolean batching) {
|
||||
if ( batching ) {
|
||||
return updateVersionExecutor(session, group,dynamicUpdate);
|
||||
}
|
||||
return mutationExecutorService.createExecutor( NoBatchKeyAccess.INSTANCE, group, session );
|
||||
|
||||
}
|
||||
|
||||
protected BatchKeyAccess resolveUpdateVersionBatchKeyAccess(boolean dynamicUpdate, SharedSessionContractImplementor session) {
|
||||
if ( !dynamicUpdate
|
||||
&& session.getTransactionCoordinator() != null
|
||||
|
|
Loading…
Reference in New Issue