hibernate/hibernate-orm · error · UnsupportedOperationException

INSERT cannot be basis for subquery

Error message

INSERT cannot be basis for subquery

What it means

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.

Source

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

	}

	public SqmQueryPart<?> getSelectQueryPart() {
		return selectQueryPart;
	}

	public void setSelectQueryPart(SqmQueryPart<?> selectQueryPart) {
		this.selectQueryPart = selectQueryPart;
	}

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

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

	@Nullable
	@Override
	public JpaPredicate getRestriction() {
		// insert has no predicate
		return null;
	}

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

	@Nonnull
	@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. 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
  2. Derive the subquery from the querySpec that feeds the insert-select
  3. Branch on statement type in generic code: skip subquery() for JpaCriteriaInsert/insert statements
  4. Model the logic as INSERT ... SELECT (subquery) — put the subquery inside the select list or where clause of the source query

Example fix

// before
JpaCriteriaInsert<Person> ins = cb.createInsert( Person.class );
Subquery<Long> sq = ins.subquery( Long.class ); // UnsupportedOperationException

// after
CriteriaQuery<Person> source = cb.createQuery( Person.class );
Subquery<Long> sq = source.subquery( Long.class );
ins.setSelectQuery( source );
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

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

Prevention

When it happens

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

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

Related errors


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