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 ;
@@ -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 ;
0 commit comments