Skip to content

Commit 21a33a8

Browse files
committed
HHH-18311 Allow constructing SqmMultiTableInsertStrategy/SqmMultiTableMutationStrategy with EntityDomainType and MappingModelCreationProcess
1 parent 8d0b78f commit 21a33a8

File tree

4 files changed

+144
-14
lines changed

4 files changed

+144
-14
lines changed

hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.hibernate.SessionEventListener;
3030
import org.hibernate.SessionFactoryObserver;
3131
import org.hibernate.context.spi.TenantSchemaMapper;
32+
import org.hibernate.metamodel.mapping.EntityMappingType;
33+
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
3234
import org.hibernate.type.TimeZoneStorageStrategy;
3335
import org.hibernate.annotations.CacheLayout;
3436
import org.hibernate.boot.SchemaAutoTooling;
@@ -195,6 +197,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
195197
private final HqlTranslator hqlTranslator;
196198
private final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
197199
private final SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy;
200+
private final Constructor<SqmMultiTableMutationStrategy> sqmMultiTableMutationStrategyConstructor;
201+
private final Constructor<SqmMultiTableInsertStrategy> sqmMultiTableInsertStrategyConstructor;
198202
private final SqmTranslatorFactory sqmTranslatorFactory;
199203
private final Boolean useOfJdbcNamedParametersEnabled;
200204
private boolean namedQueryStartupCheckingEnabled;
@@ -405,10 +409,14 @@ public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, Boo
405409
extractPropertyValue( AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY, settings );
406410
sqmMultiTableMutationStrategy =
407411
resolveSqmMutationStrategy( sqmMutationStrategyImplName, serviceRegistry, strategySelector );
412+
sqmMultiTableMutationStrategyConstructor =
413+
resolveSqmMutationStrategyConstructor( sqmMutationStrategyImplName, strategySelector );
408414
final String sqmInsertStrategyImplName =
409415
extractPropertyValue( AvailableSettings.QUERY_MULTI_TABLE_INSERT_STRATEGY, settings );
410416
sqmMultiTableInsertStrategy =
411417
resolveSqmInsertStrategy( sqmInsertStrategyImplName, serviceRegistry, strategySelector );
418+
sqmMultiTableInsertStrategyConstructor =
419+
resolveSqmInsertStrategyConstructor( sqmInsertStrategyImplName, strategySelector );
412420

413421
useOfJdbcNamedParametersEnabled =
414422
configurationService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true );
@@ -621,6 +629,7 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
621629
strategyClass -> {
622630
Constructor<SqmMultiTableMutationStrategy> dialectConstructor = null;
623631
Constructor<SqmMultiTableMutationStrategy> emptyConstructor = null;
632+
Constructor<SqmMultiTableMutationStrategy> entityBasedConstructor = null;
624633
// todo (6.0) : formalize the allowed constructor parameterizations
625634
for ( Constructor<?> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
626635
final Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
@@ -631,29 +640,59 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
631640
else if ( parameterTypes.length == 0 ) {
632641
emptyConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
633642
}
643+
else if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
644+
entityBasedConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
645+
}
634646
}
635647

636-
try {
637-
if ( dialectConstructor != null ) {
638-
return dialectConstructor.newInstance(
639-
serviceRegistry.requireService( JdbcServices.class ).getDialect()
640-
);
648+
if ( entityBasedConstructor == null ) {
649+
try {
650+
if ( dialectConstructor != null ) {
651+
return dialectConstructor.newInstance(
652+
serviceRegistry.requireService( JdbcServices.class ).getDialect()
653+
);
654+
}
655+
else if ( emptyConstructor != null ) {
656+
return emptyConstructor.newInstance();
657+
}
641658
}
642-
else if ( emptyConstructor != null ) {
643-
return emptyConstructor.newInstance();
659+
catch (Exception e) {
660+
throw new StrategySelectionException(
661+
String.format( "Could not instantiate named strategy class [%s]",
662+
strategyClass.getName() ),
663+
e
664+
);
644665
}
666+
throw new IllegalArgumentException(
667+
"Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
645668
}
646-
catch (Exception e) {
647-
throw new StrategySelectionException(
648-
String.format( "Could not instantiate named strategy class [%s]", strategyClass.getName() ),
649-
e
650-
);
669+
else {
670+
return null;
651671
}
652-
throw new IllegalArgumentException( "Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
653672
}
654673
);
655674
}
656675

676+
@SuppressWarnings("unchecked")
677+
private Constructor<SqmMultiTableMutationStrategy> resolveSqmMutationStrategyConstructor(
678+
String strategyName,
679+
StrategySelector strategySelector) {
680+
if ( strategyName == null ) {
681+
return null;
682+
}
683+
684+
Class<? extends SqmMultiTableMutationStrategy> strategyClass =
685+
strategySelector.selectStrategyImplementor( SqmMultiTableMutationStrategy.class, strategyName );
686+
for ( Constructor<?> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
687+
final Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
688+
if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
689+
return (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
690+
}
691+
}
692+
693+
return null;
694+
}
695+
657696
@SuppressWarnings("unchecked")
658697
private SqmMultiTableInsertStrategy resolveSqmInsertStrategy(
659698
String strategyName,
@@ -703,6 +742,26 @@ else if ( emptyConstructor != null ) {
703742
);
704743
}
705744

745+
@SuppressWarnings("unchecked")
746+
private Constructor<SqmMultiTableInsertStrategy> resolveSqmInsertStrategyConstructor(
747+
String strategyName,
748+
StrategySelector strategySelector) {
749+
if ( strategyName == null ) {
750+
return null;
751+
}
752+
753+
Class<? extends SqmMultiTableInsertStrategy> strategyClass =
754+
strategySelector.selectStrategyImplementor( SqmMultiTableInsertStrategy.class, strategyName );
755+
for ( Constructor<?> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
756+
final Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
757+
if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
758+
return (Constructor<SqmMultiTableInsertStrategy>) declaredConstructor;
759+
}
760+
}
761+
762+
return null;
763+
}
764+
706765
private HqlTranslator resolveHqlTranslator(
707766
String producerName,
708767
StandardServiceRegistry serviceRegistry,
@@ -923,6 +982,38 @@ public SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy() {
923982
return sqmMultiTableInsertStrategy;
924983
}
925984

985+
@Override
986+
public SqmMultiTableMutationStrategy resolveCustomSqmMultiTableMutationStrategy(EntityMappingType rootEntityDescriptor, MappingModelCreationProcess creationProcess) {
987+
if ( sqmMultiTableMutationStrategyConstructor != null ) {
988+
try {
989+
return sqmMultiTableMutationStrategyConstructor.newInstance( rootEntityDescriptor, creationProcess );
990+
}
991+
catch (Exception e) {
992+
throw new StrategySelectionException(
993+
String.format( "Could not instantiate named strategy class [%s]", sqmMultiTableMutationStrategyConstructor.getDeclaringClass().getName() ),
994+
e
995+
);
996+
}
997+
}
998+
return null;
999+
}
1000+
1001+
@Override
1002+
public SqmMultiTableInsertStrategy resolveCustomSqmMultiTableInsertStrategy(EntityMappingType rootEntityDescriptor, MappingModelCreationProcess creationProcess) {
1003+
if ( sqmMultiTableInsertStrategyConstructor != null ) {
1004+
try {
1005+
return sqmMultiTableInsertStrategyConstructor.newInstance( rootEntityDescriptor, creationProcess );
1006+
}
1007+
catch (Exception e) {
1008+
throw new StrategySelectionException(
1009+
String.format( "Could not instantiate named strategy class [%s]", sqmMultiTableInsertStrategyConstructor.getDeclaringClass().getName() ),
1010+
e
1011+
);
1012+
}
1013+
}
1014+
return null;
1015+
}
1016+
9261017
@Override
9271018
public boolean isUseOfJdbcNamedParametersEnabled() {
9281019
return useOfJdbcNamedParametersEnabled;

hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import org.hibernate.LockOptions;
1919
import org.hibernate.SessionFactoryObserver;
2020
import org.hibernate.context.spi.TenantSchemaMapper;
21+
import org.hibernate.metamodel.mapping.EntityMappingType;
22+
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
2123
import org.hibernate.type.TimeZoneStorageStrategy;
2224
import org.hibernate.annotations.CacheLayout;
2325
import org.hibernate.boot.SchemaAutoTooling;
@@ -145,6 +147,16 @@ public SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy() {
145147
return delegate.getCustomSqmMultiTableInsertStrategy();
146148
}
147149

150+
@Override
151+
public SqmMultiTableMutationStrategy resolveCustomSqmMultiTableMutationStrategy(EntityMappingType rootEntityDescriptor, MappingModelCreationProcess creationProcess) {
152+
return delegate.resolveCustomSqmMultiTableMutationStrategy( rootEntityDescriptor, creationProcess );
153+
}
154+
155+
@Override
156+
public SqmMultiTableInsertStrategy resolveCustomSqmMultiTableInsertStrategy(EntityMappingType rootEntityDescriptor, MappingModelCreationProcess creationProcess) {
157+
return delegate.resolveCustomSqmMultiTableInsertStrategy( rootEntityDescriptor, creationProcess );
158+
}
159+
148160
@Override
149161
public StatementInspector getStatementInspector() {
150162
return delegate.getStatementInspector();

hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.util.Map;
88

99
import org.hibernate.jpa.spi.JpaCompliance;
10+
import org.hibernate.metamodel.mapping.EntityMappingType;
11+
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
1012
import org.hibernate.query.criteria.ValueHandlingMode;
1113
import org.hibernate.query.hql.HqlTranslator;
1214
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
@@ -75,6 +77,22 @@ public interface QueryEngineOptions {
7577
*/
7678
SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy();
7779

80+
/**
81+
* Contract for handling SQM trees representing mutation (UPDATE or DELETE) queries
82+
* where the target of the mutation is a multi-table entity.
83+
*
84+
* @see org.hibernate.cfg.QuerySettings#QUERY_MULTI_TABLE_MUTATION_STRATEGY
85+
*/
86+
SqmMultiTableMutationStrategy resolveCustomSqmMultiTableMutationStrategy(EntityMappingType rootEntityDescriptor, MappingModelCreationProcess creationProcess);
87+
88+
/**
89+
* Contract for handling SQM trees representing insertion (INSERT) queries where the
90+
* target of the mutation is a multi-table entity.
91+
*
92+
* @see org.hibernate.cfg.QuerySettings#QUERY_MULTI_TABLE_INSERT_STRATEGY
93+
*/
94+
SqmMultiTableInsertStrategy resolveCustomSqmMultiTableInsertStrategy(EntityMappingType rootEntityDescriptor, MappingModelCreationProcess creationProcess);
95+
7896
/**
7997
* @see org.hibernate.cfg.JpaComplianceSettings
8098
*/

hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMultiTableMutationStrategyProviderStandard.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ public SqmMultiTableMutationStrategy createMutationStrategy(
3232
if ( specifiedStrategy != null ) {
3333
return specifiedStrategy;
3434
}
35-
35+
final SqmMultiTableMutationStrategy specifiedEntityBaseStrategy =
36+
options.resolveCustomSqmMultiTableMutationStrategy( rootEntityDescriptor, creationProcess );
37+
if ( specifiedEntityBaseStrategy != null ) {
38+
return specifiedEntityBaseStrategy;
39+
}
3640
return creationContext.getDialect().getFallbackSqmMutationStrategy( rootEntityDescriptor, creationContext );
3741
}
3842

@@ -47,6 +51,11 @@ public SqmMultiTableInsertStrategy createInsertStrategy(
4751
if ( specifiedStrategy != null ) {
4852
return specifiedStrategy;
4953
}
54+
final SqmMultiTableInsertStrategy specifiedEntityBaseStrategy =
55+
options.resolveCustomSqmMultiTableInsertStrategy( rootEntityDescriptor, creationProcess );
56+
if ( specifiedEntityBaseStrategy != null ) {
57+
return specifiedEntityBaseStrategy;
58+
}
5059

5160
return creationContext.getDialect().getFallbackSqmInsertStrategy( rootEntityDescriptor, creationContext );
5261
}

0 commit comments

Comments
 (0)