Skip to content

Commit 3cd1bc8

Browse files
committed
HHH-18311 Allow constructing SqmMultiTableInsertStrategy/SqmMultiTableMutationStrategy with EntityDomainType and MappingModelCreationProcess
1 parent 0930fb3 commit 3cd1bc8

File tree

4 files changed

+144
-16
lines changed

4 files changed

+144
-16
lines changed

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

Lines changed: 104 additions & 15 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;
@@ -179,6 +181,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
179181
private final HqlTranslator hqlTranslator;
180182
private final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
181183
private final SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy;
184+
private final Constructor<SqmMultiTableMutationStrategy> sqmMultiTableMutationStrategyConstructor;
185+
private final Constructor<SqmMultiTableInsertStrategy> sqmMultiTableInsertStrategyConstructor;
182186
private final SqmTranslatorFactory sqmTranslatorFactory;
183187
private final Boolean useOfJdbcNamedParametersEnabled;
184188
private boolean namedQueryStartupCheckingEnabled;
@@ -388,10 +392,14 @@ public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, Boo
388392
extractPropertyValue( QUERY_MULTI_TABLE_MUTATION_STRATEGY, settings );
389393
sqmMultiTableMutationStrategy =
390394
resolveSqmMutationStrategy( sqmMutationStrategyImplName, serviceRegistry, strategySelector );
395+
sqmMultiTableMutationStrategyConstructor =
396+
resolveSqmMutationStrategyConstructor( sqmMutationStrategyImplName, strategySelector );
391397
final String sqmInsertStrategyImplName =
392398
extractPropertyValue( QUERY_MULTI_TABLE_INSERT_STRATEGY, settings );
393399
sqmMultiTableInsertStrategy =
394400
resolveSqmInsertStrategy( sqmInsertStrategyImplName, serviceRegistry, strategySelector );
401+
sqmMultiTableInsertStrategyConstructor =
402+
resolveSqmInsertStrategyConstructor( sqmInsertStrategyImplName, strategySelector );
395403

396404
useOfJdbcNamedParametersEnabled =
397405
configurationService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true );
@@ -609,6 +617,7 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
609617
strategyClass -> {
610618
Constructor<? extends SqmMultiTableMutationStrategy> dialectConstructor = null;
611619
Constructor<? extends SqmMultiTableMutationStrategy> emptyConstructor = null;
620+
Constructor<SqmMultiTableMutationStrategy> entityBasedConstructor = null;
612621
// todo (6.0) : formalize the allowed constructor parameterizations
613622
for ( var declaredConstructor : strategyClass.getDeclaredConstructors() ) {
614623
final var parameterTypes = declaredConstructor.getParameterTypes();
@@ -622,31 +631,59 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
622631
else if ( parameterTypes.length == 0 ) {
623632
emptyConstructor = constructor;
624633
}
634+
else if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
635+
entityBasedConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
636+
}
625637
}
626638

627-
try {
628-
if ( dialectConstructor != null ) {
629-
return dialectConstructor.newInstance(
630-
serviceRegistry.requireService( JdbcServices.class ).getDialect()
631-
);
639+
if ( entityBasedConstructor == null ) {
640+
try {
641+
if ( dialectConstructor != null ) {
642+
return dialectConstructor.newInstance(
643+
serviceRegistry.requireService( JdbcServices.class ).getDialect()
644+
);
645+
}
646+
else if ( emptyConstructor != null ) {
647+
return emptyConstructor.newInstance();
648+
}
632649
}
633-
else if ( emptyConstructor != null ) {
634-
return emptyConstructor.newInstance();
650+
catch (Exception e) {
651+
throw new StrategySelectionException(
652+
"Could not instantiate named strategy class [" +
653+
strategyClass.getName() + "]",
654+
e
655+
);
635656
}
657+
throw new IllegalArgumentException(
658+
"Cannot instantiate the class [" + strategyClass.getName() + "] because it does not have a constructor that accepts a dialect or an empty constructor" );
636659
}
637-
catch (Exception e) {
638-
throw new StrategySelectionException(
639-
"Could not instantiate named strategy class [" + strategyClass.getName() + "]",
640-
e
641-
);
660+
else {
661+
return null;
642662
}
643-
throw new IllegalArgumentException( "Cannot instantiate the class ["
644-
+ strategyClass.getName()
645-
+ "] because it does not have a constructor that accepts a dialect or an empty constructor" );
646663
}
647664
);
648665
}
649666

667+
@SuppressWarnings("unchecked")
668+
private Constructor<SqmMultiTableMutationStrategy> resolveSqmMutationStrategyConstructor(
669+
String strategyName,
670+
StrategySelector strategySelector) {
671+
if ( strategyName == null ) {
672+
return null;
673+
}
674+
675+
Class<? extends SqmMultiTableMutationStrategy> strategyClass =
676+
strategySelector.selectStrategyImplementor( SqmMultiTableMutationStrategy.class, strategyName );
677+
for ( Constructor<?> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
678+
final Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
679+
if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
680+
return (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
681+
}
682+
}
683+
684+
return null;
685+
}
686+
650687
@SuppressWarnings("unchecked")
651688
private SqmMultiTableInsertStrategy resolveSqmInsertStrategy(
652689
String strategyName,
@@ -701,6 +738,26 @@ else if ( emptyConstructor != null ) {
701738
);
702739
}
703740

741+
@SuppressWarnings("unchecked")
742+
private Constructor<SqmMultiTableInsertStrategy> resolveSqmInsertStrategyConstructor(
743+
String strategyName,
744+
StrategySelector strategySelector) {
745+
if ( strategyName == null ) {
746+
return null;
747+
}
748+
749+
Class<? extends SqmMultiTableInsertStrategy> strategyClass =
750+
strategySelector.selectStrategyImplementor( SqmMultiTableInsertStrategy.class, strategyName );
751+
for ( Constructor<?> declaredConstructor : strategyClass.getDeclaredConstructors() ) {
752+
final Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
753+
if ( parameterTypes.length == 2 && parameterTypes[0] == EntityMappingType.class && parameterTypes[1] == MappingModelCreationProcess.class ) {
754+
return (Constructor<SqmMultiTableInsertStrategy>) declaredConstructor;
755+
}
756+
}
757+
758+
return null;
759+
}
760+
704761
private HqlTranslator resolveHqlTranslator(
705762
String producerName,
706763
StandardServiceRegistry serviceRegistry,
@@ -921,6 +978,38 @@ public SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy() {
921978
return sqmMultiTableInsertStrategy;
922979
}
923980

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