{"record":{"id":"9724842bbd4f6bb0","repo":"hibernate/hibernate-orm","slug":"incorrect-query-result-type-query-produces-s-b-972484","errorCode":null,"errorMessage":"Incorrect query result type: query produces '%s' but type '%s' was given","messagePattern":"Incorrect query result type: query produces '(.+?)' but type '(.+?)' was given","errorType":"exception","errorClass":"QueryTypeMismatchException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java","lineNumber":1376,"sourceCode":"\n\tprivate static boolean isMatchingDateJdbcType(Class<?> resultClass, JdbcType jdbcType) {\n\t\tif ( jdbcType != null ) {\n\t\t\treturn switch ( jdbcType.getDefaultSqlTypeCode() ) {\n\t\t\t\tcase Types.DATE -> resultClass.isAssignableFrom(java.sql.Date.class);\n\t\t\t\tcase Types.TIME -> resultClass.isAssignableFrom(java.sql.Time.class);\n\t\t\t\tcase Types.TIMESTAMP -> resultClass.isAssignableFrom(java.sql.Timestamp.class);\n\t\t\t\tdefault -> false;\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate static void throwQueryTypeMismatchException(\n\t\t\tClass<?> resultClass,\n\t\t\t@Nullable SqmExpressible<?> sqmExpressible, @Nullable Class<?> javaTypeClass) {\n\t\tthrow new QueryTypeMismatchException( String.format(\n\t\t\t\tLocale.ROOT,\n\t\t\t\t\"Incorrect query result type: query produces '%s' but type '%s' was given\",\n\t\t\t\tsqmExpressible == null ? javaTypeClass.getName() : sqmExpressible.getTypeName(),\n\t\t\t\tresultClass.getName()\n\t\t) );\n\t}\n\n\tpublic static Set<ParameterExpression<?>> getParameters(SqmStatement<?> statement) {\n\t\tfinal var parameters = statement.getSqmParameters();\n\t\treturn switch ( parameters.size() ) {\n\t\t\tcase 0 -> emptySet();\n\t\t\tcase 1 -> {\n\t\t\t\tfinal var parameter = parameters.iterator().next();\n\t\t\t\tyield parameter instanceof ValueBindJpaCriteriaParameter\n\t\t\t\t\t\t? emptySet()\n\t\t\t\t\t\t: singleton( parameter );\n\t\t\t}\n\t\t\tdefault -> {","sourceCodeStart":1358,"sourceCodeEnd":1394,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java#L1358-L1394","documentation":"Thrown as QueryTypeMismatchException (a HibernateException) by SqmUtil.throwQueryTypeMismatchException when the type produced by the query's select item is not assignable to the result class you gave when creating the query. Before executing, Hibernate compares the SQM expression's SqmExpressible type name against the expected Java class; a mismatch (query produces String, you asked for Person) fails fast instead of producing a ClassCastException later.","triggerScenarios":"session.createQuery(\"select p.name from Person p\", Person.class); selecting p.id (Long) but passing Integer.class; criteria .select(cb.count(root)) with a result class other than Long; array/compound selections where the component type does not match the expected array component class.","commonSituations":"Refactoring a query from entity select to scalar/DTO projection without updating the result class; generic DAO APIs where the caller-supplied result class drifts from the actual select; numeric type mismatches after changing an @Id generation type; tuple queries declared with the entity class.","solutions":["Make the result class match what the select produces: createQuery(hql, String.class) for 'select p.name'","Change the select to produce the expected type: 'select p from Person p' for Person.class","For multiple/scalar items use Object[] or a Tuple/construct(...) DTO result type","For numeric IDs use the exact Java type of the id attribute (usually Long)"],"exampleFix":"// before\nQuery<Person> q = session.createQuery(\"select p.name from Person p\", Person.class);\n// after\nQuery<String> q = session.createQuery(\"select p.name from Person p\", String.class);","handlingStrategy":"try-catch","validationCode":"null // the produced type is only known after SQM analysis; keep the result class and select expression in one place instead","typeGuard":"static boolean resultTypeMatches(Class<?> produced, Class<?> expected) {\n    return produced != null && produced.isAssignableFrom(expected) || expected.isAssignableFrom(produced);\n}","tryCatchPattern":"try {\n    return session.createQuery(hql, resultClass).getResultList();\n} catch (QueryTypeMismatchException e) {\n    throw new IllegalArgumentException(\n        \"Result class \" + resultClass.getName() + \" does not match select item of: \" + hql, e);\n}","preventionTips":["Derive the result class from the same source as the select expression (constant or metamodel lookup)","Write one smoke test per named query asserting its result type","For scalar selects use createQuery(hql, String.class/Long.class), for entities the entity class, for multi-select Object[] or Tuple"],"tags":["hibernate","query-result-type","classcast","orm"],"backgroundTag":"query-result-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}