hibernate/hibernate-orm · error · QueryTypeMismatchException
Incorrect query result type: query produces '%s' but type '%
Error message
Incorrect query result type: query produces '%s' but type '%s' was given
What it means
Typed query creation (createSelectionQuery/createQuery with an expected result class) calls checkResultType(): the query's actual result type must be assignable to the requested class, otherwise QueryTypeMismatchException('Incorrect query result type: query produces X but type Y was given'). It enforces the contract between the HQL select list and the Java type before execution.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java:2082
protected HqlInterpretation<?> interpretHql(String hql) {
return interpretHql( hql, null );
}
protected <R> HqlInterpretation<R> interpretHql(String hql, Class<R> resultType) {
return getFactory().getQueryEngine().interpretHql( hql, resultType );
}
protected static void checkSelectionQuery(String hql, HqlInterpretation<?> hqlInterpretation) {
if ( !( hqlInterpretation.getSqmStatement() instanceof SqmSelectStatement ) ) {
throw new IllegalSelectQueryException( "Expecting a selection query, but found '" + hql + "'", hql);
}
}
protected static <R> void checkResultType(Class<R> expectedResultType, SelectionQuery<R> query) {
final var resultType = query.getResultType();
if ( !expectedResultType.isAssignableFrom( resultType ) ) {
throw new QueryTypeMismatchException(
String.format(
Locale.ROOT,
"Incorrect query result type: query produces '%s' but type '%s' was given",
expectedResultType.getName(),
resultType.getName()
)
);
}
}
protected NamedResultSetMappingMemento getResultSetMappingMemento(String resultSetMappingName) {
final var resultSetMappingMemento =
namedObjectRepository().getResultSetMappingMemento( resultSetMappingName );
if ( resultSetMappingMemento == null ) {
throw new HibernateException( "No result set mapping with given name '" + resultSetMappingName + "'" );
}
return resultSetMappingMemento;
}View on GitHub (pinned to fad1729dce)
Solutions
- Match the class to the select list: counts are Long.class; multi-column selects need Object[]/Tuple/the exact DTO class.
- Adjust the HQL select clause to produce the requested shape (e.g., select new com.Dto(a.id, a.name)).
- Create the query untyped and map results manually when shapes vary at runtime.
Example fix
// before
Long n = session.createQuery("select count(u) from User u", Integer.class).getSingleResult();
// QueryTypeMismatchException: query produces java.lang.Long
// after
Long n = session.createQuery("select count(u) from User u", Long.class).getSingleResult(); Defensive patterns
Strategy: validation
Validate before calling
// Create untyped first, inspect the real result type, then act
SelectionQuery<?> raw = session.createSelectionQuery(hql);
Class<?> actual = raw.getResultType();
if (!expectedType.isAssignableFrom(actual)) {
throw new IllegalArgumentException(
"HQL produces " + actual.getName() + "; caller expected " + expectedType.getName());
}
@SuppressWarnings("unchecked")
SelectionQuery<T> typed = (SelectionQuery<T>) raw; Try / catch
try {
return session.createSelectionQuery(hql, expectedType).list();
} catch (QueryTypeMismatchException e) {
// dynamic HQL: fall back to untyped query with manual mapping
return mapManually(session.createSelectionQuery(hql).list());
} Prevention
- Type count queries as Long.class, never Integer/int
- Write the select list and the result class argument together, as one unit, in reviews
- Use Tuple or Object[] for multi-selects instead of guessing a scalar type
When it happens
Trigger: createQuery("select count(u) from User u", Integer.class) when count() produces Long; a projection (select new Dto(...)/multi-column) queried with the entity class; expecting a scalar when the select list yields Object[]; DTO constructor signature not matching columns.
Common situations: count queries typed as Integer/int from pre-JPA ports or naive refactors; switching between entity and DTO selects without updating the class argument; multi-select expected as scalar; Java primitives boxed to the wrong wrapper type.
Related errors
- Result type is '{}' but the query returned a '{}'
- Parameter %d of function '%s()' has type '%s', but argument
- Start and stop parameters of function '%s()' must be of the
- Step parameter of function '%s()' is of type '%s', but must
- Step parameter of function '%s()' is of type '%s', but must
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4b2aa9cc700a0618.
Report an issue: GitHub.