hibernate/hibernate-orm · error · IllegalQueryOperationException

Insert conflict do update clause is not supported

Error message

Insert conflict do update clause is not supported

What it means

The second guard of the base visitConflictClause: the default implementation supports only DO NOTHING, so an HQL insert with a 'do update' conflict clause (upsert-update) on a dialect whose translator did not override conflict handling throws IllegalQueryOperationException during translation.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:1994

				throw new IllegalQueryOperationException( "Locking with aggregate functions is not supported" );
			}
			else if ( followOnStrategy == Locking.FollowOn.IGNORE ) {
				return LockStrategy.NONE;
			}
			strategy = LockStrategy.FOLLOW_ON;
		}

		return strategy;
	}

	protected void visitConflictClause(ConflictClause conflictClause) {
		if ( conflictClause != null ) {
			// By default, we only support do nothing with an optional constraint name
			if ( !conflictClause.getConstraintColumnNames().isEmpty() ) {
				throw new IllegalQueryOperationException( "Insert conflict clause with constraint column names is not supported" );
			}
			if ( conflictClause.isDoUpdate() ) {
				throw new IllegalQueryOperationException( "Insert conflict do update clause is not supported" );
			}
		}
	}

	protected void visitStandardConflictClause(ConflictClause conflictClause) {
		if ( conflictClause == null ) {
			return;
		}

		clauseStack.push( Clause.CONFLICT );
		appendSql( " on conflict" );
		final String constraintName = conflictClause.getConstraintName();
		if ( constraintName != null ) {
			appendSql( " on constraint " );
			appendSql( constraintName );
		}
		else if ( !conflictClause.getConstraintColumnNames().isEmpty() ) {
			char separator = '(';

View on GitHub (pinned to fad1729dce)

Solutions

  1. Run the upsert-update as a native statement (MERGE, INSERT ... ON CONFLICT DO UPDATE, ON DUPLICATE KEY UPDATE) for that database.
  2. Implement the upsert in application code inside a transaction: attempt insert, catch the unique violation, then update.
  3. Restrict the HQL conflict syntax to dialects that support it (profile per-dialect HQL) and use 'do nothing' where only that is supported.

Example fix

// before — do-update conflict clause on an unsupported dialect
session.createQuery(
    "insert into Counter (id,hits) values (:i,:h) on conflict (id) do update set hits = excluded.hits")
    .executeUpdate();

// after — dialect-native upsert
em.createNativeQuery("insert into counter (id,hits) values (?,?) " +
    "on duplicate key update hits = hits + values(hits)")
  .setParameter(1, id).setParameter(2, hits).executeUpdate();
Defensive patterns

Strategy: validation

Validate before calling

if (conflictClauseHasDoUpdate(hql) && !dialectSupportsUpsertUpdate(sessionFactory)) {
    // route to native upsert or application-level insert-or-update instead of HQL
    useNativeUpsert = true;
}

Try / catch

try { session.createQuery(insertHql).executeUpdate(); }
catch (org.hibernate.query.IllegalQueryOperationException e) {
    if (e.getMessage().equals("Insert conflict do update clause is not supported")) {
        runNativeUpsertOrUpdate(insertHql);
    } else { throw e; }
}

Prevention

When it happens

Trigger: HQL 'insert ... on conflict [constraint] do update set col = ...' on a dialect using the base translator — databases without native upsert-update and without a MERGE/duplicate-key override in their SqlAstTranslator.

Common situations: Writing portable upsert HQL for PostgreSQL/MySQL and running it on a lesser-supported database; Hibernate 6.5+/6.6 upsert features enabled broadly; community dialects lagging on conflict-clause support.

Related errors


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