hibernate/hibernate-orm · error · StrategySelectionException

Could not instantiate named strategy class [{}]

Error message

Could not instantiate named strategy class [{}]

What it means

When hibernate.query.mutation_strategy names a custom SqmMultiTableMutationStrategy class, SessionFactoryOptionsBuilder tries to instantiate it via its Dialect-accepting constructor or its no-arg constructor. If the chosen constructor exists but invocation fails (constructor body throws, class is abstract, or access is denied), a StrategySelectionException wrapping the cause is thrown during SessionFactory bootstrap.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java:728

						}
						else if ( hasStrategyConstructorSignature( parameterTypes ) ) {
							entityBasedConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;
						}
					}

					if ( entityBasedConstructor == null ) {
						try {
							if ( dialectConstructor != null ) {
								return dialectConstructor.newInstance(
										serviceRegistry.requireService( JdbcServices.class ).getDialect()
								);
							}
							else if ( emptyConstructor != null ) {
								return emptyConstructor.newInstance();
							}
						}
						catch (Exception e) {
							throw new StrategySelectionException(
									"Could not instantiate named strategy class [" + strategyClass.getName() + "]",
									e
							);
						}
						throw new IllegalArgumentException( "Cannot instantiate the class [" + strategyClass.getName()
								+ "] because it does not have a constructor that accepts a dialect or an empty constructor" );
					}
					else {
						return null;
					}
				}
		);
	}

	@SuppressWarnings("unchecked")
	@Nullable
	private Constructor<SqmMultiTableMutationStrategy> resolveSqmMutationStrategyConstructor(
			String strategyName,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Read the nested cause of the StrategySelectionException — InvocationTargetException.getCause() points at the real failure inside your constructor
  2. Make the strategy class and its Dialect/no-arg constructor public
  3. Move heavy initialization out of the constructor; defer to first use when the runtime context is available
  4. If the strategy needs per-entity context, provide a public (EntityMappingType, RuntimeModelCreationContext) constructor instead

Example fix

// before:
public MyMutationStrategy(Dialect dialect) {
    this.schema = requireGlobalConfig().getSchema(); // throws NPE at bootstrap
}

// after:
public MyMutationStrategy(Dialect dialect) {
    this.dialect = dialect; // defer schema resolution to first use
}
public String schema() { return GlobalConfigHolder.schema(); }
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the strategy's constructor shape before boot
static boolean hasSupportedStrategyCtor(Class<?> c) {
    return Arrays.stream(c.getDeclaredConstructors()).anyMatch(ctor -> {
        Class<?>[] p = ctor.getParameterTypes();
        return java.lang.reflect.Modifier.isPublic(ctor.getModifiers())
            && (p.length == 0 || (p.length == 1 && Dialect.class.isAssignableFrom(p[0]))
                || (p.length == 2 && p[0] == EntityMappingType.class
                    && p[1] == RuntimeModelCreationContext.class));
    });
}

Try / catch

try {
    sessionFactory = metadata.buildSessionFactory();
} catch (StrategySelectionException e) {
    if (e.getMessage() != null && e.getMessage().contains("hibernate.query.mutation_strategy class")) {
        Throwable root = e.getCause();
        while (root.getCause() != null) root = root.getCause();
        log.error("Custom mutation strategy constructor failed: {}", root, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Setting hibernate.query.mutation_strategy=com.acme.MyStrategy where MyStrategy has a Dialect or no-arg constructor whose body throws (commonly NPE from missing services), or the class/constructor is not accessible to reflection.

Common situations: Custom strategy assumes a connection or configuration source that is null at bootstrap time; constructor performs dialect feature checks that fail on unexpected dialects; strategy class made package-private or constructor made private after refactoring; upgrading Hibernate changes constructor invocation order.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/8827e448111103e9. Report an issue: GitHub.