From 7e411943ccbfafd740fd6381e093e907ae5017c3 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 8 Oct 2024 17:24:44 +0200 Subject: [PATCH] HHH-18692 Hibernate attempts to close batched statements multiple times --- .../engine/jdbc/batch/internal/BatchImpl.java | 17 +----- .../jdbc/internal/JdbcCoordinatorImpl.java | 15 ++++- .../group/PreparedStatementDetails.java | 4 ++ .../AbstractPreparedStatementGroup.java | 58 +++++++++++++++++++ .../PreparedStatementDetailsStandard.java | 9 +++ .../PreparedStatementGroupSingleTable.java | 8 +-- .../PreparedStatementGroupStandard.java | 11 ++-- 7 files changed, 93 insertions(+), 29 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/AbstractPreparedStatementGroup.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchImpl.java index 86b59d2a6f..15c9ca7a81 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/batch/internal/BatchImpl.java @@ -162,26 +162,11 @@ public void addToBatch(JdbcValueBindings jdbcValueBindings, TableInclusionChecke if ( batchPosition == batchSizeToUse ) { notifyObserversImplicitExecution(); performExecution(); - batchPosition = 0; - batchExecuted = true; } } protected void releaseStatements() { - statementGroup.forEachStatement( (tableName, statementDetails) -> { - if ( statementDetails.getStatement() == null ) { - BATCH_LOGGER.debugf( - "PreparedStatementDetails did not contain PreparedStatement on #releaseStatements : %s", - statementDetails.getSqlString() - ); - } - else { - clearBatch( statementDetails ); - } - } ); - statementGroup.release(); - jdbcCoordinator.afterStatementExecution(); } protected void clearBatch(PreparedStatementDetails statementDetails) { @@ -299,8 +284,10 @@ protected void performExecution() { } } } ); + batchExecuted = true; } finally { + jdbcCoordinator.afterStatementExecution(); batchPosition = 0; } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java index 8581b10f00..39c6a4bde8 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorImpl.java @@ -167,8 +167,12 @@ public Batch getBatch(BatchKey key, Integer batchSize, Supplier jdbcStatementCreator, @@ -66,6 +68,7 @@ public void releaseStatement(SharedSessionContractImplementor session) { if ( statement != null ) { session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( statement ); statement = null; + toRelease = false; } } @@ -82,6 +85,7 @@ public PreparedStatement getStatement() { @Override public PreparedStatement resolveStatement() { if ( statement == null ) { + toRelease = true; statement = jdbcStatementCreator.get(); try { expectation.prepare( statement ); @@ -102,6 +106,11 @@ public Expectation getExpectation() { return expectation; } + @Override + public boolean toRelease() { + return toRelease; + } + @Override public String toString() { return "PreparedStatementDetails(" + sql + ")"; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupSingleTable.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupSingleTable.java index 59682d403d..50fd8ffc33 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupSingleTable.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupSingleTable.java @@ -8,7 +8,6 @@ import java.util.function.Predicate; import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails; -import org.hibernate.engine.jdbc.mutation.group.PreparedStatementGroup; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.sql.model.PreparableMutationOperation; @@ -20,9 +19,8 @@ * * @author Steve Ebersole */ -public class PreparedStatementGroupSingleTable implements PreparedStatementGroup { +public class PreparedStatementGroupSingleTable extends AbstractPreparedStatementGroup { private final PreparableMutationOperation jdbcMutation; - private final SharedSessionContractImplementor session; private final PreparedStatementDetails statementDetails; @@ -36,9 +34,9 @@ public PreparedStatementGroupSingleTable( PreparableMutationOperation jdbcMutation, GeneratedValuesMutationDelegate delegate, SharedSessionContractImplementor session) { + super(session); this.jdbcMutation = jdbcMutation; this.statementDetails = ModelMutationHelper.standardPreparation( jdbcMutation, delegate, session ); - this.session = session; } protected TableMapping getMutatingTableDetails() { @@ -89,7 +87,7 @@ public boolean hasMatching(Predicate filter) { @Override public void release() { if ( statementDetails != null ) { - statementDetails.releaseStatement( session ); + release( statementDetails ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupStandard.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupStandard.java index 820b72f989..5a74624e84 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/PreparedStatementGroupStandard.java @@ -16,7 +16,6 @@ import java.util.function.Supplier; import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails; -import org.hibernate.engine.jdbc.mutation.group.PreparedStatementGroup; import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.MutationStatementPreparer; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -32,11 +31,10 @@ * * @author Steve Ebersole */ -public class PreparedStatementGroupStandard implements PreparedStatementGroup { +public class PreparedStatementGroupStandard extends AbstractPreparedStatementGroup { private final MutationType mutationType; private final MutationTarget mutationTarget; private final List jdbcMutations; - private final SharedSessionContractImplementor session; private final SortedMap statementMap; @@ -47,11 +45,11 @@ public PreparedStatementGroupStandard( GeneratedValuesMutationDelegate generatedValuesDelegate, List jdbcMutations, SharedSessionContractImplementor session) { + super( session ); this.mutationType = mutationType; this.mutationTarget = mutationTarget; this.jdbcMutations = jdbcMutations; - this.session = session; this.statementMap = createStatementDetailsMap( jdbcMutations, mutationType, generatedValuesDelegate, session ); } @@ -143,10 +141,11 @@ private static PreparedStatementDetails createPreparedStatementDetails( @Override public void release() { - statementMap.forEach( (tableName, statementDetails) -> statementDetails.releaseStatement( session ) ); + statementMap.forEach( (tableName, statementDetails) -> { + release( statementDetails ); + } ); } - private static SortedMap createStatementDetailsMap( List jdbcMutations, MutationType mutationType,