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
- Use a native query: session.createNativeQuery(sql) / em.createNativeQuery(...) and apply the mapping there.
- For HQL, project into a DTO ('select new ...') or Tuple instead of a result-set mapping.
- 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
- Apply result set mappings only right after creating a native query.
- For HQL projections use DTO constructor expressions or Tuple.
- Branch shared execution helpers on NativeQuery before touching mappings.
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
- Named native query [%s] specified both a resultset-ref and a
- Named native query definition object is null
- Named native query definition name is null: {}
- Encountered unexpected content type [%s] for named native qu
- Cannot combine other returns with a collection return (" + r
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/9e248ca585279106.
Report an issue: GitHub.