hibernate/hibernate-orm · error · IllegalQueryOperationException

Insert conflict 'do update' clause with constraint name is n

Error message

Insert conflict 'do update' clause with constraint name is not supported

What it means

Hibernate 6.6+ supports HQL upserts: 'insert into ... select ... on conflict ... do update'. SQL Server cannot bind the DO UPDATE action to a named constraint the way PostgreSQL does; SQLServerLegacySqlAstTranslator.visitConflictClause() detects 'on conflict on constraint X do update' during SQL translation and aborts with IllegalQueryOperationException.

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacySqlAstTranslator.java:137

		}
	}

	@Override
	protected void renderFromClauseAfterUpdateSet(UpdateStatement statement) {
		if ( statement.getFromClause().getRoots().isEmpty() ) {
			appendSql( " from " );
			renderDmlTargetTableExpression( statement.getTargetTable() );
		}
		else {
			visitFromClause( statement.getFromClause() );
		}
	}

	@Override
	protected void visitConflictClause(ConflictClause conflictClause) {
		if ( conflictClause != null ) {
			if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
				throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
			}
		}
	}

	@Override
	protected boolean needsRecursiveKeywordInWithClause() {
		return false;
	}

	@Override
	protected void renderTableGroupJoin(TableGroupJoin tableGroupJoin, List<TableGroupJoin> tableGroupJoinCollector) {
		appendSql( WHITESPACE );
		if ( tableGroupJoin.getJoinedGroup().isLateral() ) {
			if ( tableGroupJoin.getJoinType() == SqlAstJoinType.LEFT ) {
				appendSql( "outer apply " );
			}
			else {
				appendSql( "cross apply " );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a column list as the conflict target: 'on conflict (id) do update set ...'
  2. Use 'on conflict do nothing', which needs no target
  3. Perform the upsert with a native MERGE statement on SQL Server
  4. Scan dynamic HQL for 'on conflict on constraint' before executing it against this dialect

Example fix

-- before (HQL)
insert into Customer (id, email)
select i.id, i.email from ImportRow i
on conflict on constraint customer_pkey do update set email = excluded.email

-- after (HQL)
insert into Customer (id, email)
select i.id, i.email from ImportRow i
on conflict (id) do update set email = excluded.email
Defensive patterns

Strategy: validation

Validate before calling

boolean usesConstraintTarget(String hql, Dialect dialect) {
    return hql != null
        && hql.toLowerCase( Locale.ROOT ).contains( "on conflict on constraint" )
        && dialect instanceof SQLServerLegacyDialect;
}

if ( usesConstraintTarget( hql, dialect ) ) {
    hql = hql.replaceAll( "(?i)on constraint \\S+", "(id)" ); // column-list target
}

Try / catch

try {
    return session.createMutationQuery( hql ).executeUpdate();
}
catch ( IllegalQueryOperationException e ) {
    // rewrite to 'on conflict (cols) do update' or run a native MERGE on SQL Server
    throw e;
}

Prevention

When it happens

Trigger: Executing HQL like 'insert into Customer (id, email) select ... on conflict on constraint customer_pkey do update set email = excluded.email' on SQLServerLegacyDialect, or a Criteria insert-with-conflict built with a constraint-name conflict action.

Common situations: Porting PostgreSQL-native upsert HQL to SQL Server; shared repository code used against multiple databases where constraint-name targets were chosen for convenience.

Related errors


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