Skip to content

Commit 5dd3078

Browse files
committed
HHH-18311 Allow constructing SqmMultiTableInsertStrategy/SqmMultiTableMutationStrategy with EntityDomainType and MappingModelCreationProcess
1 parent 1ec62b7 commit 5dd3078

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;
@@ -196,6 +198,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
196198
private final HqlTranslator hqlTranslator;
197199
private final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
198200
private final SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy;
201+
private final Constructor<SqmMultiTableMutationStrategy> sqmMultiTableMutationStrategyConstructor;
202+
private final Constructor<SqmMultiTableInsertStrategy> sqmMultiTableInsertStrategyConstructor;
199203
private final SqmTranslatorFactory sqmTranslatorFactory;
200204
private final Boolean useOfJdbcNamedParametersEnabled;
201205
private boolean namedQueryStartupCheckingEnabled;
@@ -406,10 +410,14 @@ public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, Boo
406410
extractPropertyValue( AvailableSettings.QUERY_MULTI_TABLE_MUTATION_STRATEGY, settings );
407411
sqmMultiTableMutationStrategy =
408412
resolveSqmMutationStrategy( sqmMutationStrategyImplName, serviceRegistry, strategySelector );
413+
sqmMultiTableMutationStrategyConstructor =
414+
resolveSqmMutationStrategyConstructor( sqmMutationStrategyImplName, strategySelector );
409415
final String sqmInsertStrategyImplName =
410416
extractPropertyValue( AvailableSettings.QUERY_MULTI_TABLE_INSERT_STRATEGY, settings );
411417
sqmMultiTableInsertStrategy =
412418
resolveSqmInsertStrategy( sqmInsertStrategyImplName, serviceRegistry, strategySelector );
419+
sqmMultiTableInsertStrategyConstructor =
420+
resolveSqmInsertStrategyConstructor( sqmInsertStrategyImplName, strategySelector );
413421

414422
useOfJdbcNamedParametersEnabled =
415423
configurationService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true );
@@ -622,6 +630,7 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
622630
strategyClass -> {
623631
Constructor<SqmMultiTableMutationStrategy> dialectConstructor = null;
624632
Constructor<SqmMultiTableMutationStrategy> emptyConstructor = null;
633+
Constructor<SqmMultiTableMutationStrategy> entityBasedConstructor = null;
625634
// todo (6.0) : formalize the allowed constructor parameterizations
626635
for ( Constructor<?> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
627636
final Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
@@ -632,29 +641,59 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
632641
else if ( parameterTypes.length == 0 ) {
633642
emptyConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
634643
}
644+
else if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
645+
entityBasedConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
646+
}
635647
}
636648

637-
try {
638-
if ( dialectConstructor != null ) {
639-
return dialectConstructor.newInstance(
640-
serviceRegistry.requireService( JdbcServices.class ).getDialect()
641-
);
649+
if ( entityBasedConstructor == null ) {
650+
try {
651+
if ( dialectConstructor != null ) {
652+
return dialectConstructor.newInstance(
653+
serviceRegistry.requireService( JdbcServices.class ).getDialect()
654+
);
655+
}
656+
else if ( emptyConstructor != null ) {
657+
return emptyConstructor.newInstance();
658+
}
642659
}
643-
else if ( emptyConstructor != null ) {
644-
return emptyConstructor.newInstance();
660+
catch (Exception e) {
661+
throw new StrategySelectionException(
662+
String.format( "Could not instantiate named strategy class [%s]",
663+
strategyClass.getName() ),
664+
e
665+
);
645666
}
667+
throw new IllegalArgumentException(
668+
"Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
646669
}
647-
catch (Exception e) {
648-
throw new StrategySelectionException(
649-
String.format( "Could not instantiate named strategy class [%s]", strategyClass.getName() ),
650-
e
651-
);
670+
else {
671+
return null;
652672
}
653-
throw new IllegalArgumentException( "Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
654673
}
655674
);
656675
}
657676

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

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

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