hibernate/hibernate-orm · error · IllegalStateException

Result set mappings can only be used with native SQL queries

Error message

Result set mappings can only be used with native SQL queries

What it means

A ResultSetMapping describes how SQL result columns map to Java values, which only makes sense for native SQL. SelectionQueryImpl (HQL/JPQL and criteria queries) implements withResultSetMapping by throwing IllegalStateException, because HQL selects already carry typed Sqm selections and no column mapping exists. Call it only on a NativeQuery.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/SelectionQueryImpl.java:384

	public <X> SelectionQueryImplementor<X> asSelectionQuery(EntityGraph<X> entityGraph) {
		return asSelectionQuery( entityGraph, GraphSemantic.LOAD );
	}

	@Override
	@Nonnull
	public <X> SelectionQueryImplementor<X> asSelectionQuery(EntityGraph<X> entityGraph, GraphSemantic graphSemantic) {
		return new SelectionQueryImpl<>(
				this,
				entityGraph.getGraphedType().getJavaType(),
				(RootGraphImplementor<X>) entityGraph,
				graphSemantic
		);
	}

	@Override
	@Nonnull
	public <S> SelectionQueryImplementor<S> withResultSetMapping(@Nonnull ResultSetMapping<S> mapping) {
		throw new IllegalStateException( "Result set mappings can only be used with native SQL queries" );
	}


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Options

	@Override
	public boolean isReadOnly() {
		return queryOptions.isReadOnly() == null
				? session.isDefaultReadOnly()
				: queryOptions.isReadOnly();
	}

	@Override
	@Nonnull
	public SelectionQueryImplementor<R> setReadOnly(boolean readOnly) {
		queryOptions.setReadOnly( readOnly );
		return this;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a native query: session.createNativeQuery(sql) / em.createNativeQuery(...) and apply the mapping there.
  2. For HQL, project into a DTO ('select new ...') or Tuple instead of a result-set mapping.
  3. In shared code, branch on NativeQuery before applying the mapping.

Example fix

// before
var q = session.createQuery("select p from Person p", Person.class); // HQL
q.withResultSetMapping(mapping); // throws

// after
var q = session.createNativeQuery("select * from person", Person.class);
q.withResultSetMapping(mapping); // NativeQuery supports result set mappings
Defensive patterns

Strategy: type-guard

Type guard

static boolean supportsResultSetMapping(org.hibernate.query.Query<?> q) {
    return q instanceof org.hibernate.query.NativeQuery;
}

Prevention

When it happens

Trigger: Calling withResultSetMapping(mapping) (or a wrapper like applyResultSetMapping) on a query produced by em.createQuery(hql) / session.createQuery(...) or from a CriteriaQuery - anything that is not a NativeQuery.

Common situations: Migrating @SqlResultSetMapping-style native queries toward HQL while keeping the mapping call; generic query-execution helpers that accept the common Query interface and unconditionally apply mappings.

Related errors


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