{"record":{"id":"96c77b80b5fd6d51","repo":"hibernate/hibernate-orm","slug":"could-not-configure-agroal-e-getmessage","errorCode":null,"errorMessage":"Could not configure Agroal: \" + e.getMessage()","messagePattern":"Could not configure Agroal: \" \\+ e\\.getMessage\\(\\)","errorType":"exception","errorClass":"ConnectionProviderConfigurationException","httpStatus":null,"severity":"error","filePath":"hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java","lineNumber":139,"sourceCode":"\t\t\t\t\tnew AgroalPropertiesReader( CONFIG_PREFIX ).readProperties( config );\n\t\t\tagroalProperties.modify()\n\t\t\t\t\t.connectionPoolConfiguration( cp -> cp.connectionFactoryConfiguration( cf -> {\n\t\t\t\tcopyProperty( properties, JdbcSettings.DRIVER, cf::connectionProviderClassName, identity() );\n\t\t\t\tcopyProperty( properties, JdbcSettings.URL, cf::jdbcUrl, identity() );\n\t\t\t\tcopyProperty( properties, JdbcSettings.USER, cf::principal, NamePrincipal::new );\n\t\t\t\tcopyProperty( properties, JdbcSettings.PASS, cf::credential, SimplePassword::new );\n\t\t\t\tcopyProperty( properties, JdbcSettings.AUTOCOMMIT, cf::autoCommit, Boolean::valueOf );\n\t\t\t\tcopyProperty( properties, JdbcSettings.LOGIN_TIMEOUT, cf::loginTimeout,\n\t\t\t\t\t\tvalue -> Duration.ofSeconds( Integer.parseInt( value ) ) );\n\t\t\t\tresolveIsolationSetting( properties, cf );\n\t\t\t\treturn cf;\n\t\t\t} ) );\n\n\t\t\tagroalDataSource = AgroalDataSource.from( agroalProperties );\n\t\t}\n\t\tcatch ( Exception e ) {\n\t\t\tCONNECTION_INFO_LOGGER.unableToInstantiateConnectionPool( e );\n\t\t\tthrow new ConnectionProviderConfigurationException(\n\t\t\t\t\t\"Could not configure Agroal: \" + e.getMessage(),  e );\n\t\t}\n\t}\n\n\tprivate static Map<String,String> toStringValuedProperties(Map<String,Object> properties) {\n\t\treturn properties.entrySet().stream()\n\t\t\t\t.collect( toMap( Map.Entry::getKey, e -> e.getValue().toString() ) );\n\t}\n\n\t// --- ConnectionProvider\n\n\t@Override\n\tpublic Connection getConnection() throws SQLException {\n\t\treturn agroalDataSource == null ? null : agroalDataSource.getConnection();\n\t}\n\n\t@Override\n\tpublic void closeConnection(Connection connection) throws SQLException {","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java#L121-L157","documentation":"Thrown while translating a query that uses a FULL JOIN on a dialect without native full-join support (MySQL, MariaDB, Sybase/Sybase ASE, H2, TiDB). Hibernate rewrites the full join as a UNION of a left-join and a right-join branch, and to order that union it must append the order-by expressions as extra select items. When the query is DISTINCT, has a GROUP BY, or a HAVING clause, adding hidden select items would change the query result, so translation aborts with this UnsupportedOperationException.","triggerScenarios":"A full join (HQL 'full join' or Criteria full join) that is translated by MySQLSqlAstTranslator/MariaDBSqlAstTranslator/SybaseSqlAstTranslator/SybaseASESqlAstTranslator/H2SqlAstTranslator/TiDBSqlAstTranslator, combined with an ORDER BY expression that is NOT in the select list, while the query also uses select distinct, group by, or having. The check fires in emulateFullJoinWithUnion only when collectFullJoinEmulationExtraSelections returned at least one extra selection.","commonSituations":"Porting an application from PostgreSQL/Oracle (native FULL OUTER JOIN) to MySQL/MariaDB; keyset or offset pagination that sorts on a non-selected column (e.g. sort by a timestamp while selecting only ids) together with distinct/group-by; report queries with aggregations over full outer joins.","solutions":["Add every ORDER BY expression to the SELECT list (for distinct queries SQL requires the sort key to be selected anyway), e.g. 'select distinct a.id, b.name ... order by b.name'.","Move the full join into a subquery and apply distinct/group-by plus ordering in the outer query, so the emulation no longer needs hidden select items.","Order by an expression that is already selected (e.g. the grouping column) instead of a column of the full-joined side.","Replace the full join with an explicit union of a left join and a right-join/anti-join written by hand, which you control fully.","Upgrade Hibernate - the source carries a TODO stating this limitation could be removed, so newer versions may lift it."],"exampleFix":"// before (MySQL/MariaDB): distinct + order by on non-selected column of full-joined side\nList<Long> ids = session.createQuery(\n    \"select distinct a.id from A a full join a.items i order by i.label\", Long.class)\n    .getResultList();\n\n// after: include the sort expression in the select list\nList<Object[]> rows = session.createQuery(\n    \"select distinct a.id, i.label from A a full join a.items i order by i.label\", Object[].class)\n    .getResultList();","handlingStrategy":"try-catch","validationCode":"// Before running: ensure every sort expression of a full-join distinct/grouped query is selected\nboolean sortKeysSelected = orderByExpressions.stream()\n    .allMatch( selectedExpressions::contains );\nif ( !sortKeysSelected && ( query.isDistinct() || query.hasGroupBy() ) ) {\n    throw new IllegalStateException(\"Add order-by expressions to the select list for full join emulation\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return em.createQuery(hql, type).getResultList();\n} catch ( UnsupportedOperationException e ) {\n    if ( e.getMessage() != null && e.getMessage().contains(\"Full join emulation\") ) {\n        // rewrite: select the sort keys or wrap the full join in a subquery\n        return runFullJoinFallback( hql );\n    }\n    throw e;\n}","preventionTips":["On MySQL/MariaDB/Sybase/H2/TiDB, keep every ORDER BY expression of full-join queries in the SELECT list.","Warm up all named/HQL queries at startup inside try-catch so dialect-unsupported shapes fail fast at boot, not in production.","Prefer sorting on shared/selected columns (ids, keys) for paginated full-join queries.","Run the test suite against the production database dialect, not only H2-in-PostgreSQL mode."],"tags":["full-join","sql","dialect-limitation","order-by","distinct","union"],"backgroundTag":"full-join-emulation","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}