HHH-16394 Statement Batch + Version + Dirty Collection leads to OptimisticLockException: Batch update returned unexpected row count from update
This commit is contained in:
parent
b2f2547d3c
commit
0b54c1d083
|
@ -22,7 +22,6 @@ import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||||
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.resource.jdbc.spi.JdbcObserver;
|
import org.hibernate.resource.jdbc.spi.JdbcObserver;
|
||||||
|
|
||||||
import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER;
|
import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER;
|
||||||
|
@ -108,8 +107,6 @@ public class BatchImpl implements Batch {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final SharedSessionContractImplementor session = (SharedSessionContractImplementor) jdbcCoordinator.getJdbcSessionOwner();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
getStatementGroup().forEachStatement( (tableName, statementDetails) -> {
|
getStatementGroup().forEachStatement( (tableName, statementDetails) -> {
|
||||||
if ( inclusionChecker != null && !inclusionChecker.include( statementDetails.getMutatingTableDetails() ) ) {
|
if ( inclusionChecker != null && !inclusionChecker.include( statementDetails.getMutatingTableDetails() ) ) {
|
||||||
|
|
|
@ -23,6 +23,8 @@ import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
|
||||||
import org.hibernate.engine.jdbc.mutation.MutationExecutor;
|
import org.hibernate.engine.jdbc.mutation.MutationExecutor;
|
||||||
import org.hibernate.engine.jdbc.mutation.ParameterUsage;
|
import org.hibernate.engine.jdbc.mutation.ParameterUsage;
|
||||||
import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions;
|
import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions;
|
||||||
|
import org.hibernate.engine.jdbc.mutation.internal.NoBatchKeyAccess;
|
||||||
|
import org.hibernate.engine.jdbc.mutation.spi.BatchKeyAccess;
|
||||||
import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService;
|
import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
@ -81,6 +83,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
||||||
private final BatchKey batchKey;
|
private final BatchKey batchKey;
|
||||||
|
|
||||||
private final MutationOperationGroup versionUpdateGroup;
|
private final MutationOperationGroup versionUpdateGroup;
|
||||||
|
private final BatchKey versionUpdateBatchkey;
|
||||||
|
|
||||||
public UpdateCoordinatorStandard(AbstractEntityPersister entityPersister, SessionFactoryImplementor factory) {
|
public UpdateCoordinatorStandard(AbstractEntityPersister entityPersister, SessionFactoryImplementor factory) {
|
||||||
super( entityPersister, factory );
|
super( entityPersister, factory );
|
||||||
|
@ -92,12 +95,17 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
||||||
if ( entityPersister.hasUpdateGeneratedProperties() ) {
|
if ( entityPersister.hasUpdateGeneratedProperties() ) {
|
||||||
// disable batching in case of update generated properties
|
// disable batching in case of update generated properties
|
||||||
this.batchKey = null;
|
this.batchKey = null;
|
||||||
|
this.versionUpdateBatchkey = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.batchKey = new BasicBatchKey(
|
this.batchKey = new BasicBatchKey(
|
||||||
entityPersister.getEntityName() + "#UPDATE",
|
entityPersister.getEntityName() + "#UPDATE",
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
this.versionUpdateBatchkey = new BasicBatchKey(
|
||||||
|
entityPersister.getEntityName() + "#UPDATE_VERSION",
|
||||||
|
null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +455,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
||||||
|
|
||||||
final EntityTableMapping mutatingTableDetails = (EntityTableMapping) versionUpdateGroup.getSingleOperation().getTableDetails();
|
final EntityTableMapping mutatingTableDetails = (EntityTableMapping) versionUpdateGroup.getSingleOperation().getTableDetails();
|
||||||
|
|
||||||
final MutationExecutor mutationExecutor = executor( session, versionUpdateGroup, false );
|
final MutationExecutor mutationExecutor = updateVersionExecutor( session, versionUpdateGroup, false );
|
||||||
|
|
||||||
final EntityVersionMapping versionMapping = entityPersister().getVersionMapping();
|
final EntityVersionMapping versionMapping = entityPersister().getVersionMapping();
|
||||||
|
|
||||||
|
@ -973,6 +981,27 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
||||||
.createExecutor( resolveBatchKeyAccess( dynamicUpdate, session ), group, session );
|
.createExecutor( resolveBatchKeyAccess( dynamicUpdate, session ), group, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MutationExecutor updateVersionExecutor(SharedSessionContractImplementor session, MutationOperationGroup group, boolean dynamicUpdate) {
|
||||||
|
return session.getSessionFactory()
|
||||||
|
.getServiceRegistry()
|
||||||
|
.getService( MutationExecutorService.class )
|
||||||
|
.createExecutor( resolveUpdateVersionBatchKeyAccess( dynamicUpdate, session ), group, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BatchKeyAccess resolveUpdateVersionBatchKeyAccess(boolean dynamicUpdate, SharedSessionContractImplementor session) {
|
||||||
|
if ( !dynamicUpdate
|
||||||
|
&& session.getTransactionCoordinator() != null
|
||||||
|
&& session.getTransactionCoordinator().isTransactionActive() ) {
|
||||||
|
return this::getVersionUpdateBatchkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoBatchKeyAccess.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BatchKey getVersionUpdateBatchkey(){
|
||||||
|
return versionUpdateBatchkey;
|
||||||
|
}
|
||||||
|
|
||||||
protected MutationOperationGroup generateDynamicUpdateGroup(
|
protected MutationOperationGroup generateDynamicUpdateGroup(
|
||||||
Object id,
|
Object id,
|
||||||
Object rowId,
|
Object rowId,
|
||||||
|
|
Loading…
Reference in New Issue