HHH-16227 - Introduce SqmMultiTableMutationStrategyProvider

This commit is contained in:
Steve Ebersole 2023-02-24 09:51:32 -06:00
parent 132ac1bd21
commit 5451ed7437
7 changed files with 140 additions and 68 deletions

View File

@ -117,6 +117,7 @@ import org.hibernate.mapping.Index;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.UserDefinedType;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.persister.entity.mutation.EntityMutationTarget;
@ -137,6 +138,7 @@ import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableInsert
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategyProvider;
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor;
@ -2492,7 +2494,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
* The {@link SqmMultiTableMutationStrategy} to use when not specified by
* {@link org.hibernate.query.spi.QueryEngineOptions#getCustomSqmMultiTableMutationStrategy}.
*
* @see org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper#resolveStrategy
* @see SqmMultiTableMutationStrategyProvider#createMutationStrategy
*/
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType entityDescriptor,
@ -2512,7 +2514,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
* The {@link SqmMultiTableInsertStrategy} to use when not specified by
* {@link org.hibernate.query.spi.QueryEngineOptions#getCustomSqmMultiTableInsertStrategy}.
*
* @see org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper#resolveInsertStrategy
* @see SqmMultiTableMutationStrategyProvider#createInsertStrategy
*/
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(
EntityMappingType entityDescriptor,

View File

@ -142,7 +142,6 @@ import org.hibernate.mapping.DependantValue;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.Table;
@ -210,9 +209,10 @@ import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sql.internal.SQLQueryParser;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategyProvider;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.Alias;
import org.hibernate.sql.Delete;
@ -4941,19 +4941,17 @@ public abstract class AbstractEntityPersister
}
}
// we need the boot model so we can have access to the Table
final RootClass rootClass = (RootClass) creationProcess.getCreationContext()
.getBootModel().getEntityBinding( entityMappingDescriptor.getRootEntityName() );
return SqmMutationStrategyHelper.resolveStrategy( rootClass, entityMappingDescriptor, creationProcess );
final ServiceRegistry serviceRegistry = creationProcess.getCreationContext().getServiceRegistry();
return serviceRegistry.getService( SqmMultiTableMutationStrategyProvider.class )
.createMutationStrategy( entityMappingDescriptor, creationProcess );
}
protected static SqmMultiTableInsertStrategy interpretSqmMultiTableInsertStrategy(
AbstractEntityPersister entityMappingDescriptor,
MappingModelCreationProcess creationProcess) {
// we need the boot model so we can have access to the Table
final RootClass rootClass = (RootClass) creationProcess.getCreationContext()
.getBootModel().getEntityBinding( entityMappingDescriptor.getRootEntityName() );
return SqmMutationStrategyHelper.resolveInsertStrategy( rootClass, entityMappingDescriptor, creationProcess );
final ServiceRegistry serviceRegistry = creationProcess.getCreationContext().getServiceRegistry();
return serviceRegistry.getService( SqmMultiTableMutationStrategyProvider.class )
.createInsertStrategy( entityMappingDescriptor, creationProcess );
}
@Override

View File

@ -0,0 +1,37 @@
/*
* 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.
*/
package org.hibernate.query.sqm.mutation.internal;
import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategyProvider;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* Initiator for SqmMultiTableMutationStrategyProvider service
*
* @author Steve Ebersole
*/
public class SqmMultiTableMutationStrategyProviderInitiator implements StandardServiceInitiator<SqmMultiTableMutationStrategyProvider> {
/**
* Singleton access
*/
public static final SqmMultiTableMutationStrategyProviderInitiator INSTANCE = new SqmMultiTableMutationStrategyProviderInitiator();
@Override
public SqmMultiTableMutationStrategyProvider initiateService(
Map<String, Object> configurationValues,
ServiceRegistryImplementor registry) {
return new SqmMultiTableMutationStrategyProviderStandard();
}
@Override
public Class<SqmMultiTableMutationStrategyProvider> getServiceInitiated() {
return SqmMultiTableMutationStrategyProvider.class;
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.
*/
package org.hibernate.query.sqm.mutation.internal;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategyProvider;
/**
* Standard SqmMultiTableMutationStrategyProvider implementation
*
* @see org.hibernate.dialect.Dialect#getFallbackSqmMutationStrategy
* @see org.hibernate.query.spi.QueryEngineOptions#getCustomSqmMultiTableMutationStrategy
*
* @author Steve Ebersole
*/
public class SqmMultiTableMutationStrategyProviderStandard implements SqmMultiTableMutationStrategyProvider {
@Override
public SqmMultiTableMutationStrategy createMutationStrategy(
EntityMappingType rootEntityDescriptor,
MappingModelCreationProcess creationProcess) {
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final SessionFactoryOptions options = creationContext.getSessionFactoryOptions();
final SqmMultiTableMutationStrategy specifiedStrategy = options.getCustomSqmMultiTableMutationStrategy();
if ( specifiedStrategy != null ) {
return specifiedStrategy;
}
return creationContext.getDialect().getFallbackSqmMutationStrategy( rootEntityDescriptor, creationContext );
}
@Override
public SqmMultiTableInsertStrategy createInsertStrategy(
EntityMappingType rootEntityDescriptor,
MappingModelCreationProcess creationProcess) {
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final SessionFactoryOptions options = creationContext.getSessionFactoryOptions();
final SqmMultiTableInsertStrategy specifiedStrategy = options.getCustomSqmMultiTableInsertStrategy();
if ( specifiedStrategy != null ) {
return specifiedStrategy;
}
return creationContext.getDialect().getFallbackSqmInsertStrategy( rootEntityDescriptor, creationContext );
}
}

View File

@ -9,17 +9,11 @@ package org.hibernate.query.sqm.mutation.internal;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.mapping.RootClass;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
import org.hibernate.sql.ast.tree.from.NamedTableReference;
import org.hibernate.sql.ast.tree.from.TableReference;
@ -31,59 +25,9 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
* @author Steve Ebersole
*/
public class SqmMutationStrategyHelper {
/**
* Singleton access
*/
public static final SqmMutationStrategyHelper INSTANCE = new SqmMutationStrategyHelper();
private SqmMutationStrategyHelper() {
}
/**
* Standard resolution of {@link SqmMultiTableMutationStrategy} to use for a given entity hierarchy.
*
* @see org.hibernate.dialect.Dialect#getFallbackSqmMutationStrategy
* @see org.hibernate.query.spi.QueryEngineOptions#getCustomSqmMultiTableMutationStrategy
*/
public static SqmMultiTableMutationStrategy resolveStrategy(
RootClass entityBootDescriptor,
EntityMappingType rootEntityDescriptor,
MappingModelCreationProcess creationProcess) {
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final SessionFactoryOptions options = creationContext.getSessionFactoryOptions();
final SqmMultiTableMutationStrategy specifiedStrategy = options.getCustomSqmMultiTableMutationStrategy();
if ( specifiedStrategy != null ) {
return specifiedStrategy;
}
// todo (6.0) : add capability define strategy per-hierarchy
return creationContext.getDialect().getFallbackSqmMutationStrategy( rootEntityDescriptor, creationContext );
}
/**
* Standard resolution of {@link SqmMultiTableInsertStrategy} to use for a given entity hierarchy.
*
* @see org.hibernate.dialect.Dialect#getFallbackSqmInsertStrategy
* @see org.hibernate.query.spi.QueryEngineOptions#getCustomSqmMultiTableInsertStrategy
*/
public static SqmMultiTableInsertStrategy resolveInsertStrategy(
RootClass entityBootDescriptor,
EntityMappingType rootEntityDescriptor,
MappingModelCreationProcess creationProcess) {
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final SessionFactoryOptions options = creationContext.getSessionFactoryOptions();
final SqmMultiTableInsertStrategy specifiedStrategy = options.getCustomSqmMultiTableInsertStrategy();
if ( specifiedStrategy != null ) {
return specifiedStrategy;
}
// todo (6.0) : add capability define strategy per-hierarchy
return creationContext.getDialect().getFallbackSqmInsertStrategy( rootEntityDescriptor, creationContext );
}
public static void visitCollectionTables(
EntityMappingType entityDescriptor,
Consumer<PluralAttributeMapping> consumer) {

View File

@ -0,0 +1,34 @@
/*
* 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.
*/
package org.hibernate.query.sqm.mutation.spi;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.service.Service;
/**
* Pluggable contract for providing custom {@link SqmMultiTableMutationStrategy} and
* {@link SqmMultiTableInsertStrategy} implementations. This is intended for use by
* hibernate-reactive to provide its custom implementations.
*
* @author Steve Ebersole
*/
public interface SqmMultiTableMutationStrategyProvider extends Service {
/**
* Determine the SqmMultiTableMutationStrategy to use for the given entity
*/
SqmMultiTableMutationStrategy createMutationStrategy(
EntityMappingType rootEntityDescriptor,
MappingModelCreationProcess creationProcess);
/**
* Determine the SqmMultiTableInsertStrategy to use for the given entity
*/
SqmMultiTableInsertStrategy createInsertStrategy(
EntityMappingType rootEntityDescriptor,
MappingModelCreationProcess creationProcess);
}

View File

@ -34,6 +34,7 @@ import org.hibernate.id.factory.internal.StandardIdentifierGeneratorFactoryIniti
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
import org.hibernate.persister.internal.PersisterFactoryInitiator;
import org.hibernate.property.access.internal.PropertyAccessStrategyResolverInitiator;
import org.hibernate.query.sqm.mutation.internal.SqmMultiTableMutationStrategyProviderInitiator;
import org.hibernate.resource.beans.spi.ManagedBeanRegistryInitiator;
import org.hibernate.resource.transaction.internal.TransactionCoordinatorBuilderInitiator;
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
@ -97,6 +98,7 @@ public final class StandardServiceInitiators {
serviceInitiators.add( EntityCopyObserverFactoryInitiator.INSTANCE );
serviceInitiators.add( JdbcValuesMappingProducerProviderInitiator.INSTANCE );
serviceInitiators.add( SqmMultiTableMutationStrategyProviderInitiator.INSTANCE );
serviceInitiators.trimToSize();