2929import org .hibernate .SessionEventListener ;
3030import org .hibernate .SessionFactoryObserver ;
3131import org .hibernate .context .spi .TenantSchemaMapper ;
32+ import org .hibernate .metamodel .mapping .EntityMappingType ;
33+ import org .hibernate .metamodel .mapping .internal .MappingModelCreationProcess ;
3234import org .hibernate .type .TimeZoneStorageStrategy ;
3335import org .hibernate .annotations .CacheLayout ;
3436import 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 ;
0 commit comments