HHH-15393 - Improve write-paths to use mapping model
This commit is contained in:
parent
7461100c39
commit
94e2b599e4
|
@ -8,14 +8,9 @@ package org.hibernate.engine.jdbc.mutation.internal;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.hibernate.engine.jdbc.batch.spi.Batch;
|
|
||||||
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
|
|
||||||
import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
|
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.OperationResultChecker;
|
import org.hibernate.engine.jdbc.mutation.OperationResultChecker;
|
||||||
|
@ -59,26 +54,14 @@ public class MutationExecutorPostInsert implements MutationExecutor {
|
||||||
|
|
||||||
private final PreparedStatementDetails identityInsertStatementDetails;
|
private final PreparedStatementDetails identityInsertStatementDetails;
|
||||||
|
|
||||||
/**
|
|
||||||
* The batched statements
|
|
||||||
*/
|
|
||||||
private final Batch batch;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any non-batched JDBC statements
|
* Any non-batched JDBC statements
|
||||||
*/
|
*/
|
||||||
private final PreparedStatementGroup nonBatchedStatementGroup;
|
private final PreparedStatementGroup secondaryTablesStatementGroup;
|
||||||
|
|
||||||
private final JdbcValueBindingsImpl valueBindings;
|
private final JdbcValueBindingsImpl valueBindings;
|
||||||
|
|
||||||
private enum StatementLocation { IDENTITY, BATCHED, NON_BATCHED }
|
public MutationExecutorPostInsert(MutationOperationGroup mutationOperationGroup, SharedSessionContractImplementor session) {
|
||||||
private final Map<String, StatementLocation> statementLocationMap = new HashMap<>();
|
|
||||||
|
|
||||||
public MutationExecutorPostInsert(
|
|
||||||
MutationOperationGroup mutationOperationGroup,
|
|
||||||
Supplier<BatchKey> batchKeySupplier,
|
|
||||||
int batchSize,
|
|
||||||
SharedSessionContractImplementor session) {
|
|
||||||
this.mutationTarget = (EntityMutationTarget) mutationOperationGroup.getMutationTarget();
|
this.mutationTarget = (EntityMutationTarget) mutationOperationGroup.getMutationTarget();
|
||||||
this.valueBindings = new JdbcValueBindingsImpl(
|
this.valueBindings = new JdbcValueBindingsImpl(
|
||||||
MutationType.INSERT,
|
MutationType.INSERT,
|
||||||
|
@ -92,12 +75,8 @@ public class MutationExecutorPostInsert implements MutationExecutor {
|
||||||
identityInsertOperation,
|
identityInsertOperation,
|
||||||
session
|
session
|
||||||
);
|
);
|
||||||
statementLocationMap.put( mutationTarget.getIdentifierTableName(), StatementLocation.IDENTITY );
|
|
||||||
|
|
||||||
final BatchKey batchKey = batchKeySupplier.get();
|
List<PreparableMutationOperation> secondaryTableMutations = null;
|
||||||
|
|
||||||
List<PreparableMutationOperation> batchedJdbcMutations = null;
|
|
||||||
List<PreparableMutationOperation> nonBatchedJdbcMutations = null;
|
|
||||||
|
|
||||||
final List<MutationOperation> operations = mutationOperationGroup.getOperations();
|
final List<MutationOperation> operations = mutationOperationGroup.getOperations();
|
||||||
for ( int i = 0; i < operations.size(); i++ ) {
|
for ( int i = 0; i < operations.size(); i++ ) {
|
||||||
|
@ -112,48 +91,17 @@ public class MutationExecutorPostInsert implements MutationExecutor {
|
||||||
assert ! (operation instanceof SelfExecutingUpdateOperation );
|
assert ! (operation instanceof SelfExecutingUpdateOperation );
|
||||||
|
|
||||||
final PreparableMutationOperation preparableMutationOperation = (PreparableMutationOperation) operation;
|
final PreparableMutationOperation preparableMutationOperation = (PreparableMutationOperation) operation;
|
||||||
if ( preparableMutationOperation.canBeBatched( batchKey, batchSize ) ) {
|
if ( secondaryTableMutations == null ) {
|
||||||
if ( batchedJdbcMutations == null ) {
|
secondaryTableMutations = new ArrayList<>();
|
||||||
batchedJdbcMutations = new ArrayList<>();
|
|
||||||
}
|
|
||||||
batchedJdbcMutations.add( preparableMutationOperation );
|
|
||||||
statementLocationMap.put( operation.getTableDetails().getTableName(), StatementLocation.BATCHED );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( nonBatchedJdbcMutations == null ) {
|
|
||||||
nonBatchedJdbcMutations = new ArrayList<>();
|
|
||||||
}
|
|
||||||
nonBatchedJdbcMutations.add( preparableMutationOperation );
|
|
||||||
statementLocationMap.put( operation.getTableDetails().getTableName(), StatementLocation.NON_BATCHED );
|
|
||||||
}
|
}
|
||||||
|
secondaryTableMutations.add( preparableMutationOperation );
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo (mutation) : consider creating single PreparedStatementGroup for all
|
|
||||||
// batched and non-batched statements. we then need a way to know whether a
|
|
||||||
// statement is batched or not. `PreparedStatementDetails#isBatched`?
|
|
||||||
|
|
||||||
if ( batchedJdbcMutations == null || batchedJdbcMutations.isEmpty() ) {
|
this.secondaryTablesStatementGroup = ModelMutationHelper.toPreparedStatementGroup(
|
||||||
this.batch = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final List<PreparableMutationOperation> batchedMutationsRef = batchedJdbcMutations;
|
|
||||||
this.batch = session.getJdbcCoordinator().getBatch2(
|
|
||||||
batchKey,
|
|
||||||
batchSize,
|
|
||||||
() -> ModelMutationHelper.toPreparedStatementGroup(
|
|
||||||
MutationType.INSERT,
|
|
||||||
mutationTarget,
|
|
||||||
batchedMutationsRef,
|
|
||||||
session
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert batch != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.nonBatchedStatementGroup = ModelMutationHelper.toPreparedStatementGroup(
|
|
||||||
MutationType.INSERT,
|
MutationType.INSERT,
|
||||||
mutationTarget,
|
mutationTarget,
|
||||||
nonBatchedJdbcMutations,
|
secondaryTableMutations,
|
||||||
session
|
session
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -174,27 +122,11 @@ public class MutationExecutorPostInsert implements MutationExecutor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PreparedStatementDetails getPreparedStatementDetails(String tableName) {
|
public PreparedStatementDetails getPreparedStatementDetails(String tableName) {
|
||||||
final StatementLocation statementLocation = statementLocationMap.get( tableName );
|
if ( mutationTarget.getIdentifierTableName().equals( tableName ) ) {
|
||||||
if ( statementLocation == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( statementLocation == StatementLocation.IDENTITY ) {
|
|
||||||
assert mutationTarget.getIdentifierTableName().equals( tableName );
|
|
||||||
return identityInsertStatementDetails;
|
return identityInsertStatementDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( statementLocation == StatementLocation.BATCHED ) {
|
return secondaryTablesStatementGroup.getPreparedStatementDetails( tableName );
|
||||||
assert batch != null;
|
|
||||||
return batch.getStatementGroup().getPreparedStatementDetails( tableName );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( statementLocation == StatementLocation.NON_BATCHED ) {
|
|
||||||
assert nonBatchedStatementGroup != null;
|
|
||||||
return nonBatchedStatementGroup.getPreparedStatementDetails( tableName );
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -215,19 +147,8 @@ public class MutationExecutorPostInsert implements MutationExecutor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nonBatchedStatementGroup != null ) {
|
if ( secondaryTablesStatementGroup != null ) {
|
||||||
nonBatchedStatementGroup.forEachStatement( (tableName, statementDetails) -> executeWithId(
|
secondaryTablesStatementGroup.forEachStatement( (tableName, statementDetails) -> executeWithId(
|
||||||
id,
|
|
||||||
tableName,
|
|
||||||
statementDetails,
|
|
||||||
inclusionChecker,
|
|
||||||
resultChecker,
|
|
||||||
session
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( batch != null ) {
|
|
||||||
batch.getStatementGroup().forEachStatement( (tableName, statementDetails) -> executeWithId(
|
|
||||||
id,
|
id,
|
||||||
tableName,
|
tableName,
|
||||||
statementDetails,
|
statementDetails,
|
||||||
|
@ -301,7 +222,7 @@ public class MutationExecutorPostInsert implements MutationExecutor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
nonBatchedStatementGroup.release();
|
secondaryTablesStatementGroup.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -69,6 +69,6 @@ public class MutationExecutorServiceInitiator implements StandardServiceInitiato
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutationExecutorService createStandardService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
|
private MutationExecutorService createStandardService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
|
||||||
return new StandardMutationExecutorService( configurationValues, registry );
|
return new StandardMutationExecutorService( configurationValues );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,7 +188,6 @@ public class MutationExecutorStandard extends AbstractMutationExecutor {
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
nonBatchedStatementGroup.release();
|
nonBatchedStatementGroup.release();
|
||||||
// todo (mutation) :implement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,12 +51,6 @@ public class PreparedStatementDetailsStandard implements PreparedStatementDetail
|
||||||
Supplier<PreparedStatement> jdbcStatementCreator,
|
Supplier<PreparedStatement> jdbcStatementCreator,
|
||||||
Expectation expectation,
|
Expectation expectation,
|
||||||
JdbcServices jdbcServices) {
|
JdbcServices jdbcServices) {
|
||||||
|
|
||||||
// todo (mutation) : have `parameterDescriptors` be passed in.
|
|
||||||
// - these descriptors being only available relative solely
|
|
||||||
// to a preparable operation, rather than more widely scoped to
|
|
||||||
// the `MutationOperation`, causes problems for self-executing operations
|
|
||||||
|
|
||||||
this.mutatingTableDetails = tableMutation.getTableDetails();
|
this.mutatingTableDetails = tableMutation.getTableDetails();
|
||||||
this.sql = sql;
|
this.sql = sql;
|
||||||
this.jdbcStatementCreator = jdbcStatementCreator;
|
this.jdbcStatementCreator = jdbcStatementCreator;
|
||||||
|
|
|
@ -17,7 +17,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.persister.entity.mutation.EntityMutationTarget;
|
import org.hibernate.persister.entity.mutation.EntityMutationTarget;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
|
||||||
import org.hibernate.sql.model.MutationOperation;
|
import org.hibernate.sql.model.MutationOperation;
|
||||||
import org.hibernate.sql.model.MutationOperationGroup;
|
import org.hibernate.sql.model.MutationOperationGroup;
|
||||||
import org.hibernate.sql.model.MutationTarget;
|
import org.hibernate.sql.model.MutationTarget;
|
||||||
|
@ -35,7 +34,7 @@ import org.hibernate.sql.model.SelfExecutingUpdateOperation;
|
||||||
public class StandardMutationExecutorService implements MutationExecutorService {
|
public class StandardMutationExecutorService implements MutationExecutorService {
|
||||||
private final int globalBatchSize;
|
private final int globalBatchSize;
|
||||||
|
|
||||||
public StandardMutationExecutorService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
|
public StandardMutationExecutorService(Map<String, Object> configurationValues) {
|
||||||
this( ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, 1 ) );
|
this( ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, 1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +65,7 @@ public class StandardMutationExecutorService implements MutationExecutorService
|
||||||
assert mutationTarget instanceof EntityMappingType;
|
assert mutationTarget instanceof EntityMappingType;
|
||||||
|
|
||||||
if ( numberOfOperations > 1 ) {
|
if ( numberOfOperations > 1 ) {
|
||||||
return new MutationExecutorPostInsert( operationGroup, batchKeySupplier, batchSizeToUse, session );
|
return new MutationExecutorPostInsert( operationGroup, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MutationExecutorPostInsertSingleTable( operationGroup, session );
|
return new MutationExecutorPostInsertSingleTable( operationGroup, session );
|
||||||
|
|
|
@ -11,4 +11,7 @@
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@Incubating
|
||||||
package org.hibernate.engine.jdbc.mutation;
|
package org.hibernate.engine.jdbc.mutation;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
|
|
@ -7,12 +7,15 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines support for performing mutation operations against collections.
|
* Defines support for performing mutation operations against collections.
|
||||||
* <p/>
|
*
|
||||||
* The names used here are logical. E.g. "inserting a row" may actually
|
* @apiNote The names used here are logical. E.g. "inserting a row" may actually
|
||||||
* execute an UPDATE statement instead of an INSERT. This is generally
|
* execute an UPDATE statement instead of an INSERT. This is generally
|
||||||
* delineated based on whether there is a collection table involved or
|
* delineated based on whether there is a collection table involved or
|
||||||
* not. In standard Hibernate terms, this breaks down to the distinction
|
* not. In standard Hibernate terms, this breaks down to the distinction
|
||||||
* between {@link org.hibernate.persister.collection.BasicCollectionPersister}
|
* between {@link org.hibernate.persister.collection.BasicCollectionPersister}
|
||||||
* and {@link org.hibernate.persister.collection.OneToManyPersister}.
|
* and {@link org.hibernate.persister.collection.OneToManyPersister}.
|
||||||
*/
|
*/
|
||||||
|
@Incubating
|
||||||
package org.hibernate.persister.collection.mutation;
|
package org.hibernate.persister.collection.mutation;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines support for performing mutation operations originating
|
||||||
|
* from persistence-context events
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
package org.hibernate.persister.entity.mutation;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
|
@ -77,7 +77,11 @@ public interface MutationOperation {
|
||||||
TableMapping getTableDetails();
|
TableMapping getTableDetails();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the JDBC parameter to be used for the specified column
|
* Find the JDBC parameter to be used for the specified column.
|
||||||
|
*
|
||||||
|
* @return The descriptor, or null if none match.
|
||||||
|
*
|
||||||
|
* @see #getJdbcValueDescriptor
|
||||||
*/
|
*/
|
||||||
JdbcValueDescriptor findValueDescriptor(String columnName, ParameterUsage usage);
|
JdbcValueDescriptor findValueDescriptor(String columnName, ParameterUsage usage);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue