{"record":{"id":"2f62ea27eb3dfaf8","repo":"hibernate/hibernate-orm","slug":"cannot-unwrap-to-requested-type-unwraptype-ge","errorCode":null,"errorMessage":"Cannot unwrap to requested type [\" + unwrapType.getName() + \"]","messagePattern":"Cannot unwrap to requested type \\[\" \\+ unwrapType\\.getName\\(\\) \\+ \"\\]","errorType":"exception","errorClass":"UnknownUnwrapTypeException","httpStatus":null,"severity":"error","filePath":"hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java","lineNumber":224,"sourceCode":"\t}\n\n\t@Override\n\tpublic boolean isUnwrappableAs(@Nonnull Class<?> unwrapType) {\n\t\treturn unwrapType.isAssignableFrom( AgroalConnectionProvider.class )\n\t\t\t|| unwrapType.isAssignableFrom( AgroalDataSource.class );\n\t}\n\n\t@Override\n\t@SuppressWarnings( \"unchecked\" )\n\tpublic <T> T unwrap(@Nonnull Class<T> unwrapType) {\n\t\tif ( unwrapType.isAssignableFrom( AgroalConnectionProvider.class ) ) {\n\t\t\treturn (T) this;\n\t\t}\n\t\telse if ( unwrapType.isAssignableFrom( AgroalDataSource.class ) ) {\n\t\t\treturn (T) agroalDataSource;\n\t\t}\n\t\telse {\n\t\t\tthrow new UnknownUnwrapTypeException( unwrapType );\n\t\t}\n\t}\n\n\t// --- Stoppable\n\n\t@Override\n\tpublic void stop() {\n\t\tif ( agroalDataSource != null ) {\n\t\t\tCONNECTION_INFO_LOGGER.cleaningUpConnectionPool(\n\t\t\t\t\tagroalDataSource.getConfiguration()\n\t\t\t\t\t\t\t.connectionPoolConfiguration()\n\t\t\t\t\t\t\t.connectionFactoryConfiguration()\n\t\t\t\t\t\t\t.jdbcUrl() );\n\t\t\tagroalDataSource.close();\n\t\t}\n\t}\n}\n","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java#L206-L242","documentation":"For a union-emulated full join, Hibernate can only order by positional references into the select list of the union branches. Ignore-case ordering would require a case-folded copy (lower/upper) of the sort column in that select list, which this emulation does not synthesize, so it rejects the query up front. This is a dialect limitation: on dialects with native FULL JOIN and native case-insensitive collation the same query works.","triggerScenarios":"An order-by created with ignore-case semantics - Criteria API Order.ignoreCase() (JPA 3.2) or SortSpecification with isIgnoreCase()==true - on a query containing a full join, translated by the MySQL/MariaDB/Sybase/SybaseASE/H2/TiDB translators. renderFullJoinEmulationSortExpression throws as soon as sortSpecification.isIgnoreCase() is true.","commonSituations":"Case-insensitive name sorting (users, cities, products) that used to run on PostgreSQL/SQL Server and is moved to MySQL/MariaDB; UI grid sorting with ignore-case flag enabled by default; JPA 3.2 migration where Order.ignoreCase() became available and developers adopted it widely.","solutions":["Replace ignoreCase() with an explicit case-folding expression and select it: order by cb.lower(root.get(\"name\")) with lower(name) in the select list.","Do case-insensitive sorting in memory after fetching, or in a wrapping query outside the full join.","Define the column with a case-insensitive collation (e.g. utf8mb4_unicode_ci on MySQL) so a plain order by is already case-insensitive.","Avoid the full join for that query so no union emulation ordering is involved."],"exampleFix":"// before: Criteria order with ignore-case + full join -> UnsupportedOperationException on MySQL\nquery.orderBy( cb.asc( root.get(\"name\") ).ignoreCase() );\n\n// after: explicit case-folding expression that is part of the select list\nquery.multiselect( root.get(\"id\"), cb.lower( root.get(\"name\") ) );\nquery.orderBy( cb.asc( cb.lower( root.get(\"name\") ) ) );","handlingStrategy":"validation","validationCode":"// Detect ignore-case ordering before executing on a full-join-emulating dialect\nboolean hasIgnoreCaseOrder = criteriaQuery.getOrderList().stream()\n    .anyMatch( o -> o instanceof JpaOrder j && j.isIgnoreCase() );\nboolean emulatingDialect = dialect instanceof MySQLDialect || dialect instanceof MariaDBDialect\n    || dialect instanceof SybaseDialect || dialect instanceof TiDBDialect;\nif ( hasIgnoreCaseOrder && usesFullJoin && emulatingDialect ) {\n    // convert to cb.lower(...) before running\n}","typeGuard":null,"tryCatchPattern":"try {\n    return query.getResultList();\n} catch ( UnsupportedOperationException e ) {\n    if ( e.getMessage() != null && e.getMessage().contains(\"ignore case ordering\") ) {\n        return sortInMemoryIgnoreCase( queryWithoutFullJoin() );\n    }\n    throw e;\n}","preventionTips":["Use explicit cb.lower()/lower() in HQL instead of Order.ignoreCase() when targeting MySQL/MariaDB/Sybase/TiDB.","Prefer case-insensitive column collations for natural case-insensitive sorting on those databases.","Smoke-test every dynamically generated sort combination against the production dialect."],"tags":["full-join","order-by","ignore-case","dialect-limitation","union"],"backgroundTag":"full-join-emulation","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}