diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java index e25a30a6ef..14581168b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java @@ -70,6 +70,7 @@ public abstract class AbstractMutationCoordinator { protected BatchKeyAccess resolveBatchKeyAccess(boolean dynamicUpdate, SharedSessionContractImplementor session) { if ( !dynamicUpdate + && !entityPersister().optimisticLockStyle().isAllOrDirty() && session.getTransactionCoordinator() != null && session.getTransactionCoordinator().isTransactionActive() ) { return this::getBatchKey; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/DeleteCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/DeleteCoordinator.java index 79189ab228..3a6ed1d643 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/DeleteCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/DeleteCoordinator.java @@ -25,6 +25,8 @@ import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.sql.model.MutationOperationGroup; import org.hibernate.sql.model.MutationType; +import org.hibernate.sql.model.ast.ColumnValueBinding; +import org.hibernate.sql.model.ast.ColumnValueBindingList; import org.hibernate.sql.model.ast.builder.MutationGroupBuilder; import org.hibernate.sql.model.ast.builder.RestrictedTableMutationBuilder; import org.hibernate.sql.model.ast.builder.TableDeleteBuilder; @@ -434,17 +436,24 @@ public class DeleteCoordinator extends AbstractMutationCoordinator { Object loadedValue) { final RestrictedTableMutationBuilder tableMutationBuilder = mutationGroupBuilder.findTableDetailsBuilder( attribute.getContainingTableExpression() ); - if ( tableMutationBuilder != null && tableMutationBuilder.getOptimisticLockBindings() != null ) { - attribute.breakDownJdbcValues( - loadedValue, - (valueIndex, value, jdbcValueMapping) -> { - if ( value != null && !tableMutationBuilder.getKeyRestrictionBindings().contains( value ) ) { - tableMutationBuilder.getOptimisticLockBindings().consume( valueIndex, value, jdbcValueMapping ); + if ( tableMutationBuilder != null ) { + final ColumnValueBindingList optimisticLockBindings = tableMutationBuilder.getOptimisticLockBindings(); + if ( optimisticLockBindings != null ) { + attribute.breakDownJdbcValues( + loadedValue, + (valueIndex, value, jdbcValueMapping) -> { + if ( !tableMutationBuilder.getKeyRestrictionBindings() + .containsColumn( + jdbcValueMapping.getSelectableName(), + jdbcValueMapping.getJdbcMapping() + ) ) { + optimisticLockBindings.consume( valueIndex, value, jdbcValueMapping ); + } } - } - , - session - ); + , + session + ); + } } // else there is no actual delete statement for that table, // generally indicates we have an on-delete=cascade situation diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBinding.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBinding.java index d87ac11582..6107831ecd 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBinding.java @@ -6,6 +6,8 @@ */ package org.hibernate.sql.model.ast; +import java.util.Objects; + import org.hibernate.sql.ast.tree.expression.ColumnReference; /** @@ -38,4 +40,21 @@ public class ColumnValueBinding { public String toString() { return "ColumnValueBinding(" + valueExpression + ")"; } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + ColumnValueBinding that = (ColumnValueBinding) o; + return Objects.equals( columnReference, that.columnReference ); + } + + @Override + public int hashCode() { + return Objects.hash( columnReference ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java index 41a92cad9d..ad72092c74 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBindingList.java @@ -13,6 +13,7 @@ import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.SelectableMapping; +import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.model.ast.builder.ColumnValueBindingBuilder; @Internal @@ -68,6 +69,16 @@ public class ColumnValueBindingList extends ArrayList implem ); } + public boolean containsColumn(String columnName, JdbcMapping jdbcMapping) { + final ColumnReference reference = new ColumnReference( mutatingTable, columnName, jdbcMapping ); + for ( int i = 0; i < size(); i++ ) { + if ( get( i ).getColumnReference().equals( reference ) ) { + return true; + } + } + return false; + } + @Override public String toString() { return "ColumnValueBindingList" + super.toString();