{"record":{"id":"6cc5c13ae7e0c4da","repo":"hibernate/hibernate-orm","slug":"dialect-does-not-support-values-lists-for-insert-s","errorCode":null,"errorMessage":"Dialect does not support values lists for insert statements","messagePattern":"Dialect does not support values lists for insert statements","errorType":"exception","errorClass":"IllegalQueryOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java","lineNumber":1803,"sourceCode":"\n\tprotected void renderMergeUpdateClause(List<Assignment> assignments, Predicate wherePredicate) {\n\t\tif ( wherePredicate != null ) {\n\t\t\tappendSql( \" and \" );\n\t\t\tclauseStack.push( Clause.WHERE );\n\t\t\twherePredicate.accept( this );\n\t\t\tclauseStack.pop();\n\t\t}\n\t\tappendSql( \" then update\" );\n\t\trenderSetClause( assignments );\n\t}\n\n\tprotected void visitValuesList(List<Values> valuesList) {\n\t\tvisitValuesListStandard( valuesList );\n\t}\n\n\tprotected final void visitValuesListStandard(List<Values> valuesList) {\n\t\tif ( valuesList.size() != 1 && !dialect.supportsValuesListForInsert() ) {\n\t\t\tthrow new IllegalQueryOperationException( \"Dialect does not support values lists for insert statements\" );\n\t\t}\n\t\tappendSql(\"values\");\n\t\tfinal Stack<Clause> clauseStack = getClauseStack();\n\t\ttry {\n\t\t\tclauseStack.push( Clause.VALUES );\n\t\t\tfor ( int i = 0; i < valuesList.size(); i++ ) {\n\t\t\t\tif ( i != 0 ) {\n\t\t\t\t\tappendSql( COMMA_SEPARATOR_CHAR );\n\t\t\t\t}\n\t\t\t\tappendSql( \" (\" );\n\t\t\t\tfinal List<Expression> expressions = valuesList.get( i ).getExpressions();\n\t\t\t\tfor ( int j = 0; j < expressions.size(); j++ ) {\n\t\t\t\t\tif ( j != 0 ) {\n\t\t\t\t\t\tappendSql( COMMA_SEPARATOR_CHAR );\n\t\t\t\t\t}\n\t\t\t\t\texpressions.get( j ).accept( this );\n\t\t\t\t}\n\t\t\t\tappendSql( ')' );","sourceCodeStart":1785,"sourceCodeEnd":1821,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java#L1785-L1821","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before — multi-row VALUES list on Oracle < 23c\nsession.createQuery(\n    \"insert into Person (id,name) values (:i1,:n1),(:i2,:n2)\").executeUpdate();\n\n// after — per-row inserts with JDBC batching (hibernate.jdbc.batch_size=50)\nfor (Person p : batch) { em.persist(p); }","handlingStrategy":"validation","validationCode":"org.hibernate.dialect.Dialect d = sessionFactory.getJdbcServices().getDialect();\nif (rows.size() > 1 && !d.supportsValuesListForInsert()) {\n    // dialect (e.g., Oracle < 23c) cannot take multi-row VALUES\n    rows.forEach(this::insertOne); // or use persist() with JDBC batching\n    return;\n}","typeGuard":null,"tryCatchPattern":"try { session.createQuery(multiRowInsertHql).executeUpdate(); }\ncatch (org.hibernate.query.IllegalQueryOperationException e) {\n    if (e.getMessage().equals(\"Dialect does not support values lists for insert statements\")) {\n        rows.forEach(this::insertOne);\n    } else { throw e; }\n}","preventionTips":["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."],"tags":["hibernate","orm","insert","oracle","batch","dialect-capability"],"backgroundTag":"multi-row-insert-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}