{"record":{"id":"2c2983bb0a7c5c9f","repo":"hibernate/hibernate-orm","slug":"unmapped-polymorphic-reference-cannot-be-used-as-a","errorCode":null,"errorMessage":"Unmapped polymorphic reference cannot be used as a target of 'cross join'","messagePattern":"Unmapped polymorphic reference cannot be used as a target of 'cross join'","errorType":"exception","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java","lineNumber":2256,"sourceCode":"\t\treturn extractAlias( ctx );\n\t}\n\n\tprotected String extractAlias(HqlParser.VariableContext ctx) {\n\t\treturn SqmTreeCreationHelper.extractAlias( ctx, this );\n\t}\n\n\t@Override\n\tpublic final SqmCrossJoin<?, ?> visitCrossJoin(HqlParser.CrossJoinContext ctx) {\n\t\tthrow new UnsupportedOperationException( \"Unexpected call to #visitCrossJoin, see #consumeCrossJoin\" );\n\t}\n\n\tprotected <T> void consumeCrossJoin(HqlParser.CrossJoinContext parserJoin, SqmRoot<T> sqmRoot) {\n\t\tfinal String name = getEntityName( parserJoin.entityName() );\n\n\t\tfinal var entityDescriptor = getJpaMetamodel().resolveHqlEntityReference( name );\n\n\t\tif ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) {\n\t\t\tthrow new SemanticException( \"Unmapped polymorphic reference cannot be used as a target of 'cross join'\",\n\t\t\t\t\tquery );\n\t\t}\n\t\tfinal var join = new SqmCrossJoin<>(\n\t\t\t\t(SqmEntityDomainType<T>) entityDescriptor,\n\t\t\t\textractAlias( parserJoin.variable() ),\n\t\t\t\tsqmRoot\n\t\t);\n\n\t\tprocessingStateStack.getCurrent().getPathRegistry().register( join );\n\n\t\t// CROSS joins are always added to the root\n\t\tsqmRoot.addSqmJoin( join );\n\t}\n\n\tprivate JpaMetamodel getJpaMetamodel() {\n\t\treturn getCreationContext().getJpaMetamodel();\n\t}\n","sourceCodeStart":2238,"sourceCodeEnd":2274,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java#L2238-L2274","documentation":"consumeCrossJoin resolves the 'cross join' target entity name and rejects SqmPolymorphicRootDescriptor targets: an unmapped polymorphic reference has no single table set to cross join against, so Hibernate throws SemanticException rather than expanding the polymorphism.","triggerScenarios":"'from Employee e cross join java.lang.Object o'; 'cross join' against a package-namespace polymorphic name that resolves to multiple entities.","commonSituations":"Migrating native cross joins over broad type sets into HQL; generic query builders joining whatever name the user supplies without validating it maps to one entity.","solutions":["Cross join a concrete mapped entity instead of the polymorphic reference","If polymorphic behavior is needed, query the polymorphic root at top level and join associations explicitly","Validate user-supplied join targets against the metamodel before building the HQL"],"exampleFix":"// before\nselect e, o from Employee e cross join java.lang.Object o\n\n// after\nselect e, d from Employee e cross join Department d","handlingStrategy":"validation","validationCode":"static boolean crossJoinTargetIsConcrete(EntityManagerFactory emf, String name) {\n    return emf.getMetamodel().getEntities().stream().anyMatch(e -> e.getName().equals(name));\n}\n// reject cross join targets that are namespace/polymorphic names before building HQL\nif (!crossJoinTargetIsConcrete(emf, joinTarget)) throw new IllegalArgumentException(\"Cross join target must be a concrete entity: \" + joinTarget);","typeGuard":null,"tryCatchPattern":"try {\n    return em.createQuery(hql, Object[].class).getResultList();\n} catch (org.hibernate.query.sqm.SemanticException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"'cross join'\")) {\n        throw new IllegalArgumentException(\"Replace the polymorphic cross join target with a concrete entity\", e);\n    }\n    throw e;\n}","preventionTips":["Validate user-supplied join targets against the metamodel before composing HQL","Use concrete entity names for every join target; polymorphism belongs at the root, not the cross join"],"tags":["hql","cross-join","polymorphism","hibernate"],"backgroundTag":"polymorphic-query-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}