hibernate/hibernate-orm · error · IllegalArgumentException

Cannot instantiate the class [{}] because it does not have a

Error message

Cannot instantiate the class [{}] because it does not have a constructor that accepts a dialect or an empty constructor

What it means

For a custom class named by hibernate.query.mutation_strategy, SessionFactoryOptionsBuilder scans declared constructors looking for one of two supported shapes: a single-argument Dialect constructor, or a no-arg constructor (a (EntityMappingType, RuntimeModelCreationContext) constructor defers instantiation per entity). If none of these exists, it throws IllegalArgumentException explaining the class cannot be instantiated. This is a constructor-shape mismatch, not an invocation failure.

Source

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

					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,
			StrategySelector strategySelector) {
		if ( strategyName != null ) {
			final var strategyClass =
					strategySelector.selectStrategyImplementor( SqmMultiTableMutationStrategy.class, strategyName );
			for ( var declaredConstructor : strategyClass.getDeclaredConstructors() ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add a public constructor taking exactly one org.hibernate.dialect.Dialect argument
  2. Or add a public no-argument constructor
  3. Or provide a public constructor with exactly (EntityMappingType, RuntimeModelCreationContext) for per-entity strategies
  4. Keep at least one of the supported constructors when refactoring

Example fix

// before:
public MyMutationStrategy(ConnectionProvider cp) { ... } // only constructor

// after:
public MyMutationStrategy(Dialect dialect) {
    this.dialect = dialect;
    this.cp = null; // resolve lazily if needed
}
public MyMutationStrategy(ConnectionProvider cp) { ... } // keep for your own use
Defensive patterns

Strategy: validation

Validate before calling

// fail fast if the custom strategy lacks a supported constructor
Class<?> strategy = Class.forName(props.getProperty("hibernate.query.mutation_strategy"));
boolean ok = Arrays.stream(strategy.getDeclaredConstructors()).anyMatch(c -> {
    Class<?>[] p = c.getParameterTypes();
    return p.length == 0 || Dialect.class == p[0]
        || (p.length == 2 && p[0] == EntityMappingType.class && p[1] == RuntimeModelCreationContext.class);
});
if (!ok) throw new IllegalStateException("Strategy needs (Dialect), (), or (EntityMappingType, RuntimeModelCreationContext) ctor");

Type guard

static boolean hasHibernateStrategyConstructor(Class<?> c) {
    return Arrays.stream(c.getDeclaredConstructors()).anyMatch(ctor -> {
        Class<?>[] p = ctor.getParameterTypes();
        return 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 (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("does not have a constructor")) {
        // add a (Dialect) or no-arg constructor to the named class, then rebuild
    }
    throw e;
}

Prevention

When it happens

Trigger: Registering a SqmMultiTableMutationStrategy implementation that only offers constructors with other parameter lists, e.g. MyStrategy(ConnectionProvider), MyStrategy(int), or MyStrategy(Dialect, Settings).

Common situations: Writing a custom strategy from scratch without matching Hibernate's expected constructor contract; refactoring a working strategy's constructor signature; strategy originally built for constructor injection frameworks.

Related errors


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