{"record":{"id":"4aaeabe5ff965a31","repo":"hibernate/hibernate-orm","slug":"insert-cannot-be-basis-for-subquery","errorCode":null,"errorMessage":"INSERT cannot be basis for subquery","messagePattern":"INSERT cannot be basis for subquery","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/SqmInsertSelectStatement.java","lineNumber":142,"sourceCode":"\t}\n\n\tpublic SqmQueryPart<?> getSelectQueryPart() {\n\t\treturn selectQueryPart;\n\t}\n\n\tpublic void setSelectQueryPart(SqmQueryPart<?> selectQueryPart) {\n\t\tthis.selectQueryPart = selectQueryPart;\n\t}\n\n\t@Override\n\tpublic <X> X accept(SemanticQueryWalker<X> walker) {\n\t\treturn walker.visitInsertSelectStatement( 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 cannot be basis for subquery\" );\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic JpaPredicate getRestriction() {\n\t\t// insert has no predicate\n\t\treturn null;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmInsertSelectStatement<T> setInsertionTargetPaths(@Nonnull Path<?>... insertionTargetPaths) {\n\t\tsuper.setInsertionTargetPaths( insertionTargetPaths );\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\t@Override","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/SqmInsertSelectStatement.java#L124-L160","documentation":"SqmInsertSelectStatement.subquery throws UnsupportedOperationException because the JPA AbstractQuery.subquery() contract (derive a correlated subquery from this query) is meaningless for a DML statement: an INSERT ... SELECT cannot contain its own correlated subquery rooted on the insert itself, and SQL has no INSERT-in-subquery form. The method exists on the interface hierarchy; Hibernate implements it as an explicit rejection for insert-select statements.","triggerScenarios":"Calling `insertStatement.subquery( SomeType.class )` on a JpaCriteriaInsert obtained from HibernateCriteriaBuilder's insert-select factory; generic criteria-processing code that handles all AbstractQuery subtypes uniformly and calls subquery() on each; reflectively invoking the full AbstractQuery API on any statement type.","commonSituations":"Utility frameworks (query enhancers, audit interceptors, count-wrappers) that accept AbstractQuery/CommonAbstractContract and try to derive subqueries; porting SELECT-query code paths to INSERT statements without branching on statement type; IDE autocomplete driving the call on an object typed as AbstractQuery.","solutions":["Create the subquery on the source SELECT query instead: build the select as a CriteriaQuery and call subquery() on it, then attach the result to the insert","Derive the subquery from the querySpec that feeds the insert-select","Branch on statement type in generic code: skip subquery() for JpaCriteriaInsert/insert statements","Model the logic as INSERT ... SELECT (subquery) — put the subquery inside the select list or where clause of the source query"],"exampleFix":"// before\nJpaCriteriaInsert<Person> ins = cb.createInsert( Person.class );\nSubquery<Long> sq = ins.subquery( Long.class ); // UnsupportedOperationException\n\n// after\nCriteriaQuery<Person> source = cb.createQuery( Person.class );\nSubquery<Long> sq = source.subquery( Long.class );\nins.setSelectQuery( source );","handlingStrategy":"type-guard","validationCode":"if (statement instanceof org.hibernate.query.criteria.JpaCriteriaInsert) {\n    throw new IllegalArgumentException(\"subquery() not available on insert statements\");\n}","typeGuard":"static boolean canHostSubquery(jakarta.persistence.criteria.AbstractQuery<?> q) {\n    return !(q instanceof org.hibernate.query.criteria.JpaCriteriaInsert<?>);\n}","tryCatchPattern":null,"preventionTips":["Branch generic criteria handling on JpaCriteriaInsert before calling AbstractQuery methods","Derive subqueries only from CriteriaQuery/SubQuery objects","Keep DML and query pipelines separate in your data-access layer"],"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"}