HHH-16959 Fail to batch delete entities with nested embeddeds

This commit is contained in:
Andrea Boriero 2023-07-26 10:05:22 +02:00
parent 1df44f7416
commit 43e34ea81e
4 changed files with 50 additions and 10 deletions

View File

@ -70,6 +70,7 @@ public abstract class AbstractMutationCoordinator {
protected BatchKeyAccess resolveBatchKeyAccess(boolean dynamicUpdate, SharedSessionContractImplementor session) { protected BatchKeyAccess resolveBatchKeyAccess(boolean dynamicUpdate, SharedSessionContractImplementor session) {
if ( !dynamicUpdate if ( !dynamicUpdate
&& !entityPersister().optimisticLockStyle().isAllOrDirty()
&& session.getTransactionCoordinator() != null && session.getTransactionCoordinator() != null
&& session.getTransactionCoordinator().isTransactionActive() ) { && session.getTransactionCoordinator().isTransactionActive() ) {
return this::getBatchKey; return this::getBatchKey;

View File

@ -25,6 +25,8 @@ import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.persister.entity.AbstractEntityPersister; import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.sql.model.MutationOperationGroup; import org.hibernate.sql.model.MutationOperationGroup;
import org.hibernate.sql.model.MutationType; 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.MutationGroupBuilder;
import org.hibernate.sql.model.ast.builder.RestrictedTableMutationBuilder; import org.hibernate.sql.model.ast.builder.RestrictedTableMutationBuilder;
import org.hibernate.sql.model.ast.builder.TableDeleteBuilder; import org.hibernate.sql.model.ast.builder.TableDeleteBuilder;
@ -434,17 +436,24 @@ public class DeleteCoordinator extends AbstractMutationCoordinator {
Object loadedValue) { Object loadedValue) {
final RestrictedTableMutationBuilder<?, ?> tableMutationBuilder = final RestrictedTableMutationBuilder<?, ?> tableMutationBuilder =
mutationGroupBuilder.findTableDetailsBuilder( attribute.getContainingTableExpression() ); mutationGroupBuilder.findTableDetailsBuilder( attribute.getContainingTableExpression() );
if ( tableMutationBuilder != null && tableMutationBuilder.getOptimisticLockBindings() != null ) { if ( tableMutationBuilder != null ) {
attribute.breakDownJdbcValues( final ColumnValueBindingList optimisticLockBindings = tableMutationBuilder.getOptimisticLockBindings();
loadedValue, if ( optimisticLockBindings != null ) {
(valueIndex, value, jdbcValueMapping) -> { attribute.breakDownJdbcValues(
if ( value != null && !tableMutationBuilder.getKeyRestrictionBindings().contains( value ) ) { loadedValue,
tableMutationBuilder.getOptimisticLockBindings().consume( valueIndex, value, jdbcValueMapping ); (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, // else there is no actual delete statement for that table,
// generally indicates we have an on-delete=cascade situation // generally indicates we have an on-delete=cascade situation

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.sql.model.ast; package org.hibernate.sql.model.ast;
import java.util.Objects;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
/** /**
@ -38,4 +40,21 @@ public class ColumnValueBinding {
public String toString() { public String toString() {
return "ColumnValueBinding(" + valueExpression + ")"; 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 );
}
} }

View File

@ -13,6 +13,7 @@ import org.hibernate.engine.jdbc.mutation.ParameterUsage;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.model.ast.builder.ColumnValueBindingBuilder; import org.hibernate.sql.model.ast.builder.ColumnValueBindingBuilder;
@Internal @Internal
@ -68,6 +69,16 @@ public class ColumnValueBindingList extends ArrayList<ColumnValueBinding> 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 @Override
public String toString() { public String toString() {
return "ColumnValueBindingList" + super.toString(); return "ColumnValueBindingList" + super.toString();