hibernate/hibernate-orm · error · SemanticException
Unmapped polymorphic reference cannot be used as a target of
Error message
Unmapped polymorphic reference cannot be used as a target of 'cross join'
What it means
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.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java:2256
return extractAlias( ctx );
}
protected String extractAlias(HqlParser.VariableContext ctx) {
return SqmTreeCreationHelper.extractAlias( ctx, this );
}
@Override
public final SqmCrossJoin<?, ?> visitCrossJoin(HqlParser.CrossJoinContext ctx) {
throw new UnsupportedOperationException( "Unexpected call to #visitCrossJoin, see #consumeCrossJoin" );
}
protected <T> void consumeCrossJoin(HqlParser.CrossJoinContext parserJoin, SqmRoot<T> sqmRoot) {
final String name = getEntityName( parserJoin.entityName() );
final var entityDescriptor = getJpaMetamodel().resolveHqlEntityReference( name );
if ( entityDescriptor instanceof SqmPolymorphicRootDescriptor ) {
throw new SemanticException( "Unmapped polymorphic reference cannot be used as a target of 'cross join'",
query );
}
final var join = new SqmCrossJoin<>(
(SqmEntityDomainType<T>) entityDescriptor,
extractAlias( parserJoin.variable() ),
sqmRoot
);
processingStateStack.getCurrent().getPathRegistry().register( join );
// CROSS joins are always added to the root
sqmRoot.addSqmJoin( join );
}
private JpaMetamodel getJpaMetamodel() {
return getCreationContext().getJpaMetamodel();
}
View on GitHub (pinned to fad1729dce)
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
Example fix
// before select e, o from Employee e cross join java.lang.Object o // after select e, d from Employee e cross join Department d
Defensive patterns
Strategy: validation
Validate before calling
static boolean crossJoinTargetIsConcrete(EntityManagerFactory emf, String name) {
return emf.getMetamodel().getEntities().stream().anyMatch(e -> e.getName().equals(name));
}
// reject cross join targets that are namespace/polymorphic names before building HQL
if (!crossJoinTargetIsConcrete(emf, joinTarget)) throw new IllegalArgumentException("Cross join target must be a concrete entity: " + joinTarget); Try / catch
try {
return em.createQuery(hql, Object[].class).getResultList();
} catch (org.hibernate.query.sqm.SemanticException e) {
if (e.getMessage() != null && e.getMessage().contains("'cross join'")) {
throw new IllegalArgumentException("Replace the polymorphic cross join target with a concrete entity", e);
}
throw e;
} Prevention
- 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
When it happens
Trigger: 'from Employee e cross join java.lang.Object o'; 'cross join' against a package-namespace polymorphic name that resolves to multiple entities.
Common situations: 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.
Related errors
- NON_ENTITY_NAME
- UNMAPPED_POLYMORPHISM
- Implicitly-polymorphic domain path in subquery '${name}'
- Discriminator cannot be de-referenced
- Cannot apply TREAT operator to discriminator path
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/2c2983bb0a7c5c9f.
Report an issue: GitHub.