hibernate/hibernate-orm · error · IllegalQueryOperationException
Dialect does not support values lists for insert statements
Error message
Dialect does not support values lists for insert statements
What it means
visitValuesListStandard emits 'values (..), (..), ..' for inserts and first checks dialect.supportsValuesListForInsert(). If the statement has more than one values tuple and the dialect cannot consume a multi-row VALUES list, translation stops with IllegalQueryOperationException. Classic case: Oracle before 23ai does not support multi-row VALUES inserts.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:1803
protected void renderMergeUpdateClause(List<Assignment> assignments, Predicate wherePredicate) {
if ( wherePredicate != null ) {
appendSql( " and " );
clauseStack.push( Clause.WHERE );
wherePredicate.accept( this );
clauseStack.pop();
}
appendSql( " then update" );
renderSetClause( assignments );
}
protected void visitValuesList(List<Values> valuesList) {
visitValuesListStandard( valuesList );
}
protected final void visitValuesListStandard(List<Values> valuesList) {
if ( valuesList.size() != 1 && !dialect.supportsValuesListForInsert() ) {
throw new IllegalQueryOperationException( "Dialect does not support values lists for insert statements" );
}
appendSql("values");
final Stack<Clause> clauseStack = getClauseStack();
try {
clauseStack.push( Clause.VALUES );
for ( int i = 0; i < valuesList.size(); i++ ) {
if ( i != 0 ) {
appendSql( COMMA_SEPARATOR_CHAR );
}
appendSql( " (" );
final List<Expression> expressions = valuesList.get( i ).getExpressions();
for ( int j = 0; j < expressions.size(); j++ ) {
if ( j != 0 ) {
appendSql( COMMA_SEPARATOR_CHAR );
}
expressions.get( j ).accept( this );
}
appendSql( ')' );View on GitHub (pinned to fad1729dce)
Solutions
- Split the statement into one insert per row, or use EntityManager.persist() with JDBC batching enabled (hibernate.jdbc.batch_size) which does not need VALUES lists.
- On Oracle 23ai, make sure the dialect detects version >= 23 (set hibernate.dialect or jakarta.persistence.database-version) so supportsValuesListForInsert() is true.
- Use a native multi-row INSERT ALL / vendor-specific batch insert for bulk loads.
Example fix
// before — multi-row VALUES list on Oracle < 23c
session.createQuery(
"insert into Person (id,name) values (:i1,:n1),(:i2,:n2)").executeUpdate();
// after — per-row inserts with JDBC batching (hibernate.jdbc.batch_size=50)
for (Person p : batch) { em.persist(p); } Defensive patterns
Strategy: validation
Validate before calling
org.hibernate.dialect.Dialect d = sessionFactory.getJdbcServices().getDialect();
if (rows.size() > 1 && !d.supportsValuesListForInsert()) {
// dialect (e.g., Oracle < 23c) cannot take multi-row VALUES
rows.forEach(this::insertOne); // or use persist() with JDBC batching
return;
} Try / catch
try { session.createQuery(multiRowInsertHql).executeUpdate(); }
catch (org.hibernate.query.IllegalQueryOperationException e) {
if (e.getMessage().equals("Dialect does not support values lists for insert statements")) {
rows.forEach(this::insertOne);
} else { throw e; }
} Prevention
- Enable hibernate.jdbc.batch_size and use persist() instead of multi-row HQL inserts for portability.
- Verify the dialect detects the real database version (Oracle 23ai supports VALUES lists).
- Feature-detect once at startup: if (!dialect.supportsValuesListForInsert()) disable the multi-row path.
When it happens
Trigger: HQL 'insert into Entity (...) values (...), (...), ...' or JPA CriteriaInsert with multiple value tuples, executed on a dialect where Dialect.supportsValuesListForInsert() returns false (notably Oracle pre-23c).
Common situations: Batch-loading data via multi-row HQL inserts; the same code running on PostgreSQL in dev but Oracle in production; upgrading to Hibernate 6.4+ where HQL multi-row insert values were introduced; Oracle version misdetected so the dialect thinks it is < 23c.
Related errors
- Insert conflict clause with constraint column names is not s
- Insert conflict 'do update' clause with constraint name is n
- Can't emulate conflict clause with constraint name for more
- Dialect does not support constraint name in conflict clause
- Insert conflict do update clause is not supported
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/6cc5c13ae7e0c4da.
Report an issue: GitHub.