hibernate/hibernate-orm · error · UnsupportedOperationException

INSERT query cannot be sub-query

Error message

INSERT query cannot be sub-query

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/SqmInsertValuesStatement.java:146

			verifyInsertTypesMatch( insertionTargetPaths, sqmValues.getExpressions() );
		}
	}

	public List<SqmValues> getValuesList() {
		return valuesList == null
				? Collections.emptyList()
				: Collections.unmodifiableList( valuesList );
	}

	@Override
	public <X> X accept(SemanticQueryWalker<X> walker) {
		return walker.visitInsertValuesStatement( this );
	}

	@Nonnull
	@Override
	public <U> Subquery<U> subquery(@Nonnull EntityType<U> type) {
		throw new UnsupportedOperationException( "INSERT query cannot be sub-query" );
	}

	@Nullable
	@Override
	public JpaPredicate getRestriction() {
		return null;
	}

	@Nonnull
	@Override
	public SqmInsertValuesStatement<T> setInsertionTargetPaths(@Nonnull Path<?>... insertionTargetPaths) {
		super.setInsertionTargetPaths( insertionTargetPaths );
		return this;
	}

	@Nonnull
	@Override
	public SqmInsertValuesStatement<T> setInsertionTargetPaths(@Nonnull List<? extends Path<?>> insertionTargetPaths) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Attach subqueries to a separate CriteriaQuery/SubQuery used as a parameter value or comparison expression, not to the insert statement
  2. 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
  3. In generic code, guard with `instanceof JpaCriteriaInsert` and skip subquery handling
  4. Compute the subquery result in Java beforehand and bind it as a parameter value

Example fix

// before
JpaCriteriaInsertValues<Person> ins = cb.insertValues( Person.class );
Subquery<LocalDate> sq = ins.subquery( LocalDate.class ); // UnsupportedOperationException

// after
CriteriaQuery<LocalDate> q = cb.createQuery( LocalDate.class );
Subquery<LocalDate> sq = q.subquery( LocalDate.class );
ins.values( cb.parameter( Person.class ).get( "startDate" ) );
Defensive patterns

Strategy: type-guard

Validate before calling

if (statement instanceof org.hibernate.query.criteria.JpaCriteriaInsertValues) {
    throw new IllegalArgumentException("subquery() not available on insert-values statements");
}

Type guard

static boolean canHostSubquery(jakarta.persistence.criteria.AbstractQuery<?> q) {
    return !(q instanceof org.hibernate.query.criteria.JpaCriteriaInsertValues<?>);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/eb402cf5883a8f97. Report an issue: GitHub.