hibernate/hibernate-orm · error · IllegalQueryOperationException
Dialect does not support constraint name in conflict clause
Error message
Dialect does not support constraint name in conflict clause
What it means
visitInsertStatementEmulateMerge rewrites an HQL insert-with-conflict-clause as a database MERGE statement; used by translators for DB2, SQL Server, Oracle, Sybase/ASE, HANA, H2, and HSQLDB when the dialect has no native upsert. A MERGE statement matches rows by predicate and cannot target a named constraint, so if the SQM conflict clause has a non-null constraint name the translation aborts with IllegalQueryOperationException before any SQL is emitted.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:1464
return expression.getExpressionType().getSingleJdbcMapping().getJdbcType();
}
protected void visitInsertSource(InsertSelectStatement statement) {
if ( statement.getSourceSelectStatement() != null ) {
statement.getSourceSelectStatement().accept( this );
}
else {
visitValuesList( statement.getValuesList() );
}
}
protected void visitInsertStatementEmulateMerge(InsertSelectStatement statement) {
assert statement.getConflictClause() != null;
final ConflictClause conflictClause = statement.getConflictClause();
final String constraintName = conflictClause.getConstraintName();
if ( constraintName != null ) {
throw new IllegalQueryOperationException( "Dialect does not support constraint name in conflict clause" );
}
appendSql( "merge into " );
clauseStack.push( Clause.MERGE );
renderNamedTableReference( statement.getTargetTable(), LockMode.NONE );
clauseStack.pop();
appendSql(" using " );
final List<ColumnReference> targetColumnReferences = statement.getTargetColumns();
final List<String> columnNames = new ArrayList<>( targetColumnReferences.size() );
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
columnNames.add( targetColumnReference.getColumnExpression() );
}
final DerivedTableReference derivedTableReference;
if ( statement.getSourceSelectStatement() != null ) {
derivedTableReference = new QueryPartTableReference(
new SelectStatement( statement.getSourceSelectStatement() ),View on GitHub (pinned to fad1729dce)
Solutions
- Drop the constraint name from the conflict clause — 'on conflict do nothing' or 'on conflict (col1, col2) ...' works through the MERGE emulation.
- If you must target a specific constraint, run a native MERGE/upsert statement for that dialect.
- For SQL Server/Oracle newer versions, ensure the dialect version is detected correctly so native upsert/MERGE paths with conflict-column support are used.
Example fix
// before — named constraint cannot be represented in the MERGE emulation
session.createQuery(
"insert into Customer (id,email) values (:i,:e) on conflict on constraint uk_email do nothing")
.executeUpdate();
// after — use conflict column names instead of the constraint name
session.createQuery(
"insert into Customer (id,email) values (:i,:e) on conflict (email) do nothing")
.executeUpdate(); Defensive patterns
Strategy: validation
Validate before calling
org.hibernate.dialect.Dialect d = sessionFactory.getJdbcServices().getDialect();
boolean mergeEmulatedUpsert = d instanceof org.hibernate.dialect.DB2Dialect
|| d instanceof org.hibernate.dialect.SQLServerDialect
|| d instanceof org.hibernate.dialect.SybaseASEDialect
|| d instanceof org.hibernate.dialect.HANADialect;
if (mergeEmulatedUpsert && constraintName != null) {
// MERGE emulation cannot target a named constraint
constraintName = null; // or switch to conflict column names
} Try / catch
try { session.createQuery(insertHql).executeUpdate(); }
catch (org.hibernate.query.IllegalQueryOperationException e) {
if (e.getMessage().equals("Dialect does not support constraint name in conflict clause")) {
session.createQuery(insertHql.replace(" on constraint " + name, "")).executeUpdate();
} else { throw e; }
} Prevention
- Never name constraints in conflict clauses of portable HQL; use column names or omit.
- Keep a per-dialect map of supported upsert syntax and validate before building HQL.
- Test upsert HQL against every database your app supports.
When it happens
Trigger: HQL 'insert ... on conflict on constraint <name> [do nothing | do update ...]' executed on a dialect whose translator routes upserts through visitInsertStatementEmulateMerge (DB2, SQL Server, Oracle pre-native-upsert, Sybase ASE, HANA, H2, HSQLDB).
Common situations: Writing database-agnostic upsert HQL and testing it on H2 while targeting SQL Server/Oracle; copying PostgreSQL ON CONFLICT ON CONSTRAINT syntax to DB2; Hibernate 6.5+ HQL insert conflict feature enabled in multi-dialect apps.
Related errors
- Insert conflict 'do update' clause with constraint name is n
- Insert conflict 'do update' clause with constraint name is n
- Insert conflict 'do update' clause with constraint name is n
- Can't emulate conflict clause with constraint name for more
- Insert conflict clause with constraint column names is not s
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/57eeaa7b425497b8.
Report an issue: GitHub.