hibernate/hibernate-orm · critical · UnsupportedOperationException

CteMutationStrategy can only be used with Dialects that supp

Error message

CteMutationStrategy can only be used with Dialects that support CTE that can take UPDATE or DELETE statements as well

What it means

CteMutationStrategy implements bulk UPDATE/DELETE for multi-table entities via data-modifying CTEs and likewise requires Dialect.supportsNonQueryWithCTE() (true only on PostgreSQL, CockroachDB, SQL Server, DB2). Forcing this strategy on any other dialect throws UnsupportedOperationException while the SessionFactory is built, so the application fails to start.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteMutationStrategy.java:72

	private final SessionFactoryImplementor sessionFactory;
	private final CteTable idCteTable;

	public CteMutationStrategy(
			EntityMappingType rootEntityType,
			RuntimeModelCreationContext runtimeModelCreationContext) {
		this( rootEntityType.getEntityPersister(), runtimeModelCreationContext );
	}

	public CteMutationStrategy(
			EntityPersister rootDescriptor,
			RuntimeModelCreationContext runtimeModelCreationContext) {
		this.rootDescriptor = rootDescriptor;
		this.sessionFactory = runtimeModelCreationContext.getSessionFactory();

		final Dialect dialect = runtimeModelCreationContext.getDialect();

		if ( !dialect.supportsNonQueryWithCTE() ) {
			throw new UnsupportedOperationException(
					getClass().getSimpleName() +
							" can only be used with Dialects that support CTE that can take UPDATE or DELETE statements as well"
			);
		}

		this.idCteTable = CteTable.createIdTable( ID_TABLE_NAME,
				runtimeModelCreationContext.getMetadata().getEntityBinding( rootDescriptor.getEntityName() ) );
	}

	@Override
	public MultiTableHandlerBuildResult buildHandler(SqmDeleteOrUpdateStatement<?> sqmStatement, DomainParameterXref domainParameterXref, DomainQueryExecutionContext context) {
		final MutableObject<JdbcParameterBindings> firstJdbcParameterBindings = new MutableObject<>();
		final MultiTableHandler multiTableHandler = sqmStatement instanceof SqmDeleteStatement<?> sqmDelete
				? buildHandler( sqmDelete, domainParameterXref, context, firstJdbcParameterBindings)
				: buildHandler( (SqmUpdateStatement<?>) sqmStatement, domainParameterXref, context, firstJdbcParameterBindings );
		return new MultiTableHandlerBuildResult( multiTableHandler, firstJdbcParameterBindings.get() );
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Drop the forced `hibernate.query.mutation_strategy=cte` property on non-CTE databases
  2. Scope CTE strategy settings to per-dialect configuration profiles
  3. Verify at bootstrap: only build with the CTE strategy when the configured dialect reports supportsNonQueryWithCTE()

Example fix

# before (application.properties, MySQL deployment)
spring.jpa.properties.hibernate.query.mutation_strategy=cte

# after
# removed; Hibernate auto-selects a strategy the dialect supports
Defensive patterns

Strategy: validation

Validate before calling

// Profile-scoped config: enable CTE mutation strategy only when supported
Dialect d = (Dialect) Class.forName(configuredDialect)
        .getDeclaredConstructor().newInstance();
if (!d.supportsNonQueryWithCTE()) {
    properties.remove("hibernate.query.mutation_strategy");
}

Try / catch

try {
    emf = new Configuration().configure().buildSessionFactory();
} catch (HibernateException e) {
    if (e.getCause() instanceof UnsupportedOperationException uoe
            && uoe.getMessage().contains("CteMutationStrategy")) {
        throw new ConfigurationError(
            "Drop hibernate.query.mutation_strategy=cte for this dialect", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring `hibernate.query.mutation_strategy=cte` on MySQL/MariaDB (or any dialect without data-modifying CTEs); auto-selecting mutation strategies based on a global property rather than the actual database.

Common situations: Same family as CteInsertStrategy: config snippets for PostgreSQL upsert/bulk-DML performance pasted into projects later deployed on MySQL; multi-environment deployments sharing one properties file; version upgrades where the setting became applicable to more statement types.

Related errors


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