{"record":{"id":"805b80693987c8ad","repo":"hibernate/hibernate-orm","slug":"treated-cross-joins-doesn-t-support-explicit-alias","errorCode":null,"errorMessage":"Treated cross joins doesn't support explicit alias","messagePattern":"Treated cross joins doesn't support explicit alias","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmTreatedCrossJoin.java","lineNumber":80,"sourceCode":"\t\tfinal var existing = context.getCopy( this );\n\t\tif ( existing != null ) {\n\t\t\treturn existing;\n\t\t}\n\t\tfinal var path = context.registerCopy(\n\t\t\t\tthis,\n\t\t\t\tnew SqmTreatedCrossJoin<>(\n\t\t\t\t\t\tgetNavigablePath(),\n\t\t\t\t\t\twrappedPath.copy( context ),\n\t\t\t\t\t\ttreatTarget\n\t\t\t\t)\n\t\t);\n\t\tcopyTo( path, context );\n\t\treturn path;\n\t}\n\n\t@Override\n\tpublic void setExplicitAlias(@Nullable String explicitAlias) {\n\t\tthrow new UnsupportedOperationException(\"Treated cross joins doesn't support explicit alias\");\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmEntityDomainType<S> getTreatTarget() {\n\t\treturn treatTarget;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmEntityDomainType<S> getModel() {\n\t\treturn treatTarget;\n\t}\n\n\t@Override\n\tpublic SqmCrossJoin<L, T> getWrappedPath() {\n\t\treturn wrappedPath;\n\t}","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmTreatedCrossJoin.java#L62-L98","documentation":"A treated cross join wraps an SqmCrossJoin (an entity name referenced directly in FROM, or a criteria cross join) under TREAT. The wrapper intentionally rejects setExplicitAlias because aliasing is owned by the underlying cross join node — assigning a second alias to the treat result would corrupt the FROM clause — so it throws UnsupportedOperationException('Treated cross joins doesn't support explicit alias').","triggerScenarios":"Calling .alias(...) (JPA Selection.alias) or otherwise setting an explicit alias on the node returned by crossJoinRoot.treatAs(Sub.class) in the criteria API; HQL constructs that bind an alias token to a treated entity-name from-element.","commonSituations":"Criteria queries that cross-join an entity and immediately TREAT it, then try to alias the treated node; code generators that call alias() on every selection; mixing root.alias() and treated.alias() in the same query.","solutions":["Set the alias on the underlying cross join before treating: root.alias(\"b\") then root.treatAs(Book.class), and reference the treated node without its own alias.","Restructure the query as an association join (root.join(\"books\")) with treat, which supports aliases normally.","If the alias is only needed for ordering/selection references, reference the original root's alias instead.","Check newer Hibernate 6.x releases — treat alias handling has been progressively improved; upgrade if the query shape is valid HQL."],"exampleFix":"// before\nJpaFrom<?, Product> treated = ((JpaFrom<?, Product>) root).treatAs(Book.class);\ntreated.alias(\"b\"); // UnsupportedOperationException\n// after\nroot.alias(\"b\"); // alias the underlying from-element first\nJpaFrom<?, Book> treated = ((JpaFrom<?, Product>) root).treatAs(Book.class);\nquery.where(cb.equal(treated.get(\"isbn\"), \"...\")); // reference without its own alias","handlingStrategy":"validation","validationCode":"// Apply aliases only to from-elements that accept them; alias the source BEFORE treating\nJpaFrom<?, Product> src = (JpaFrom<?, Product>) root.alias(\"b\");\nJpaFrom<?, Book> treated = src.treatAs(Book.class);\n// do NOT call treated.alias(...) on a treated cross join","typeGuard":"static boolean aliasable(Selection<?> sel) {\n    return !(sel instanceof SqmTreatedCrossJoin); // treated cross joins reject explicit aliases\n}","tryCatchPattern":"try {\n    selection.alias(alias);\n} catch (UnsupportedOperationException e) {\n    // treated cross join: alias was already set on the wrapped join; skip\n}","preventionTips":["Always set the alias on the original from-element before treatAs.","Prefer association joins (root.join(...)) over cross joins when combining with TREAT.","In generated query code, track which nodes are treated wrappers and never re-alias them."],"tags":["hibernate","criteria-api","treat","cross-join","alias","unsupported-operation"],"backgroundTag":"unsupported-alias-on-treat","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}