29
29
import org .hibernate .SessionEventListener ;
30
30
import org .hibernate .SessionFactoryObserver ;
31
31
import org .hibernate .context .spi .TenantSchemaMapper ;
32
+ import org .hibernate .metamodel .mapping .EntityMappingType ;
33
+ import org .hibernate .metamodel .mapping .internal .MappingModelCreationProcess ;
32
34
import org .hibernate .type .TimeZoneStorageStrategy ;
33
35
import org .hibernate .annotations .CacheLayout ;
34
36
import org .hibernate .boot .SchemaAutoTooling ;
@@ -179,6 +181,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
179
181
private final HqlTranslator hqlTranslator ;
180
182
private final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy ;
181
183
private final SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy ;
184
+ private final Constructor <SqmMultiTableMutationStrategy > sqmMultiTableMutationStrategyConstructor ;
185
+ private final Constructor <SqmMultiTableInsertStrategy > sqmMultiTableInsertStrategyConstructor ;
182
186
private final SqmTranslatorFactory sqmTranslatorFactory ;
183
187
private final Boolean useOfJdbcNamedParametersEnabled ;
184
188
private boolean namedQueryStartupCheckingEnabled ;
@@ -388,10 +392,14 @@ public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, Boo
388
392
extractPropertyValue ( QUERY_MULTI_TABLE_MUTATION_STRATEGY , settings );
389
393
sqmMultiTableMutationStrategy =
390
394
resolveSqmMutationStrategy ( sqmMutationStrategyImplName , serviceRegistry , strategySelector );
395
+ sqmMultiTableMutationStrategyConstructor =
396
+ resolveSqmMutationStrategyConstructor ( sqmMutationStrategyImplName , strategySelector );
391
397
final String sqmInsertStrategyImplName =
392
398
extractPropertyValue ( QUERY_MULTI_TABLE_INSERT_STRATEGY , settings );
393
399
sqmMultiTableInsertStrategy =
394
400
resolveSqmInsertStrategy ( sqmInsertStrategyImplName , serviceRegistry , strategySelector );
401
+ sqmMultiTableInsertStrategyConstructor =
402
+ resolveSqmInsertStrategyConstructor ( sqmInsertStrategyImplName , strategySelector );
395
403
396
404
useOfJdbcNamedParametersEnabled =
397
405
configurationService .getSetting ( CALLABLE_NAMED_PARAMS_ENABLED , BOOLEAN , true );
@@ -609,6 +617,7 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
609
617
strategyClass -> {
610
618
Constructor <? extends SqmMultiTableMutationStrategy > dialectConstructor = null ;
611
619
Constructor <? extends SqmMultiTableMutationStrategy > emptyConstructor = null ;
620
+ Constructor <SqmMultiTableMutationStrategy > entityBasedConstructor = null ;
612
621
// todo (6.0) : formalize the allowed constructor parameterizations
613
622
for ( var declaredConstructor : strategyClass .getDeclaredConstructors () ) {
614
623
final var parameterTypes = declaredConstructor .getParameterTypes ();
@@ -622,31 +631,59 @@ private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
622
631
else if ( parameterTypes .length == 0 ) {
623
632
emptyConstructor = constructor ;
624
633
}
634
+ else if ( parameterTypes .length == 2 && parameterTypes [0 ] == EntityMappingType .class && parameterTypes [1 ] == MappingModelCreationProcess .class ) {
635
+ entityBasedConstructor = (Constructor <SqmMultiTableMutationStrategy >) declaredConstructor ;
636
+ }
625
637
}
626
638
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
+ }
632
649
}
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
+ );
635
656
}
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" );
636
659
}
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 ;
642
662
}
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" );
646
663
}
647
664
);
648
665
}
649
666
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
+
650
687
@ SuppressWarnings ("unchecked" )
651
688
private SqmMultiTableInsertStrategy resolveSqmInsertStrategy (
652
689
String strategyName ,
@@ -701,6 +738,26 @@ else if ( emptyConstructor != null ) {
701
738
);
702
739
}
703
740
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
+
704
761
private HqlTranslator resolveHqlTranslator (
705
762
String producerName ,
706
763
StandardServiceRegistry serviceRegistry ,
@@ -921,6 +978,38 @@ public SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy() {
921
978
return sqmMultiTableInsertStrategy ;
922
979
}
923
980
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
+
924
1013
@ Override
925
1014
public boolean isUseOfJdbcNamedParametersEnabled () {
926
1015
return useOfJdbcNamedParametersEnabled ;
0 commit comments