{"record":{"id":"eb402cf5883a8f97","repo":"hibernate/hibernate-orm","slug":"insert-query-cannot-be-sub-query","errorCode":null,"errorMessage":"INSERT query cannot be sub-query","messagePattern":"INSERT query cannot be sub-query","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/SqmInsertValuesStatement.java","lineNumber":146,"sourceCode":"\t\t\tverifyInsertTypesMatch( insertionTargetPaths, sqmValues.getExpressions() );\n\t\t}\n\t}\n\n\tpublic List<SqmValues> getValuesList() {\n\t\treturn valuesList == null\n\t\t\t\t? Collections.emptyList()\n\t\t\t\t: Collections.unmodifiableList( valuesList );\n\t}\n\n\t@Override\n\tpublic <X> X accept(SemanticQueryWalker<X> walker) {\n\t\treturn walker.visitInsertValuesStatement( this );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <U> Subquery<U> subquery(@Nonnull EntityType<U> type) {\n\t\tthrow new UnsupportedOperationException( \"INSERT query cannot be sub-query\" );\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic JpaPredicate getRestriction() {\n\t\treturn null;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmInsertValuesStatement<T> setInsertionTargetPaths(@Nonnull Path<?>... insertionTargetPaths) {\n\t\tsuper.setInsertionTargetPaths( insertionTargetPaths );\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmInsertValuesStatement<T> setInsertionTargetPaths(@Nonnull List<? extends Path<?>> insertionTargetPaths) {","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/SqmInsertValuesStatement.java#L128-L164","documentation":"SqmInsertValuesStatement.subquery throws UnsupportedOperationException for the same reason as insert-select: the JPA AbstractQuery.subquery() contract cannot apply to a DML statement. An INSERT ... VALUES is not a query expression — it cannot be nested or correlated — so any attempt to derive a subquery from it is rejected at the API level rather than producing invalid SQL later.","triggerScenarios":"Calling `insertValuesStatement.subquery( type )` on a JpaCriteriaInsertValues from `cb.insertValues(...)`/equivalent; shared helpers that take AbstractQuery and unconditionally call subquery(); attempts to wrap a values-insert as an exists/count subquery at runtime.","commonSituations":"Generic query-manipulation layers (e.g., adding tenant filters or soft-delete checks via subqueries) applied uniformly to every query object; refactoring a criteria SELECT pipeline into INSERT statements; misunderstanding that in HQL/criteria only SELECT queries (and their parts) can host subqueries.","solutions":["Attach subqueries to a separate CriteriaQuery/SubQuery used as a parameter value or comparison expression, not to the insert statement","Move conditions needing subqueries into the WHERE of an insert-select variant: convert `insert ... values` into `insert ... select ... from dual-like source` if the dialect supports it","In generic code, guard with `instanceof JpaCriteriaInsert` and skip subquery handling","Compute the subquery result in Java beforehand and bind it as a parameter value"],"exampleFix":"// before\nJpaCriteriaInsertValues<Person> ins = cb.insertValues( Person.class );\nSubquery<LocalDate> sq = ins.subquery( LocalDate.class ); // UnsupportedOperationException\n\n// after\nCriteriaQuery<LocalDate> q = cb.createQuery( LocalDate.class );\nSubquery<LocalDate> sq = q.subquery( LocalDate.class );\nins.values( cb.parameter( Person.class ).get( \"startDate\" ) );","handlingStrategy":"type-guard","validationCode":"if (statement instanceof org.hibernate.query.criteria.JpaCriteriaInsertValues) {\n    throw new IllegalArgumentException(\"subquery() not available on insert-values statements\");\n}","typeGuard":"static boolean canHostSubquery(jakarta.persistence.criteria.AbstractQuery<?> q) {\n    return !(q instanceof org.hibernate.query.criteria.JpaCriteriaInsertValues<?>);\n}","tryCatchPattern":null,"preventionTips":["Treat INSERT statements as terminals — never derive subqueries from them","Precompute subquery results in Java and bind as parameters when nesting is impossible","Type-check statement kinds in shared query interceptors"],"tags":["hibernate","criteria-api","insert","subquery","unsupported-operation"],"backgroundTag":"criteria-api-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}