hibernate/hibernate-orm · error · UnsupportedOperationException

Mutating table reference should be handled by the statement

Error message

Mutating table reference should be handled by the statement visitation

What it means

MutatingTableReference is the table reference inside insert/update/delete statements. Its accept() deliberately throws UnsupportedOperationException because mutation rendering must walk the whole statement (TableInsert/TableUpdate/TableDelete) so the walker sees parameters, optional-table handling and returning clauses in context. A generic SqlAstWalker cannot render a mutating table reference in isolation.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/model/ast/MutatingTableReference.java:54

	@Override
	public String getIdentificationVariable() {
		return null;
	}

	@Override
	public String getTableId() {
		return getTableName();
	}

	@Override
	public boolean isOptional() {
		return tableMapping.isOptional();
	}

	@Override
	public void accept(SqlAstWalker sqlTreeWalker) {
		throw new UnsupportedOperationException( "Mutating table reference should be handled by the statement visitation" );
	}

	@Override
	public Boolean visitAffectedTableNames(Function<String, Boolean> nameCollector) {
		return nameCollector.apply( getTableName() );
	}

	@Override
	public TableReference resolveTableReference(
			NavigablePath navigablePath,
			String tableExpression) {
		if ( getTableName().equals( tableExpression ) ) {
			return this;
		}

		throw new IllegalArgumentException(
				String.format(
						Locale.ROOT,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Visit the containing statement instead: tableInsert.accept(walker) / tableUpdate.accept(walker) - statement visitation handles its mutating table reference
  2. Special-case MutatingTableReference in your walker and route to the mutation statement
  3. Use visitAffectedTableNames(...) (already implemented) when you only need the affected table names
  4. Never route mutation ASTs through select-statement walkers

Example fix

// before
mutatingTableReference.accept( genericWalker ); // throws

// after
mutationStatement.accept( walker ); // TableInsert/TableUpdate/TableDelete drives its own table reference
Defensive patterns

Strategy: validation

Validate before calling

if ( ref instanceof MutatingTableReference ) {
    mutationStatement.accept( walker ); // statement drives its own table reference
} else {
    ref.accept( walker );
}

Type guard

boolean isMutatingReference(TableReference ref) {
    return ref instanceof MutatingTableReference;
}

Prevention

When it happens

Trigger: Passing a MutatingTableReference to a generic AST walker - e.g. utilities that call accept() on every TableReference found in an AST that mixes selects and mutations; reusing a select-statement walker or analyzer over mutation statements.

Common situations: Custom dialect statement emitters and SQL renderers; AST analysis/visitation utilities that iterate table references without special-casing mutation statements; code written against select-only ASTs later pointed at mutations.

Related errors


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