hibernate/hibernate-orm · error · UnsupportedOperationException
Setting a predicate for a plural part join is unsupported
Error message
Setting a predicate for a plural part join is unsupported
What it means
SqmPluralPartJoin is Hibernate's internal SQM node for joins that target a collection *part* (the pseudo-attributes exposed by a plural path, i.e. element()/index()/keys()). These joins are synthetic: Hibernate derives their join condition itself while building the query, so SqmPluralPartJoin.getJoinPredicate() always returns null and setJoinPredicate() unconditionally throws UnsupportedOperationException. Attaching a user-defined ON/WITH predicate to a collection-part join is therefore not supported by design.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmPluralPartJoin.java:102
)
);
copyTo( path, context );
return path;
}
@Override
public @Nonnull SqmFrom<?, O> getLhs() {
return castNonNull( super.getLhs() );
}
@Override
public @Nullable SqmPredicate getJoinPredicate() {
return null;
}
@Override
public void setJoinPredicate(@Nullable SqmPredicate predicate) {
throw new UnsupportedOperationException( "Setting a predicate for a plural part join is unsupported" );
}
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitPluralPartJoin( this );
}
@Nonnull
@Override
public <S extends T> SqmTreatedPluralPartJoin<O, T, S> treatAs(@Nonnull Class<S> treatJavaType) {
return treatAs( nodeBuilder().getDomainModel().entity( treatJavaType ) );
}
@Nonnull
@Override
public <S extends T> SqmTreatedPluralPartJoin<O, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {
return treatAs( treatTarget, null );
}View on GitHub (pinned to fad1729dce)
Solutions
- Move the restriction from the ON clause into the query's WHERE clause (for inner joins the result is equivalent)
- Join the plural attribute itself ('join p.nicknames n') instead of its element()/index() part, then apply on() to that SqmBagJoin/SqmSetJoin
- Replace the joined restriction with an EXISTS/IN subquery when the predicate must scope which elements are matched
- If a real ON predicate is genuinely required, remap the target as an entity association (@OneToMany over entities / @ManyToOne) instead of an @ElementCollection
Example fix
// before (HQL) select n from Person p join p.nicknames.element n on n = 'Bob' // after select n from Person p join p.nicknames n where n = 'Bob'
Defensive patterns
Strategy: type-guard
Validate before calling
import org.hibernate.query.sqm.tree.spi.domain.SqmPluralPartJoin; boolean supportsOn = !(join instanceof SqmPluralPartJoin);
Type guard
static boolean supportsOnPredicate(Join<?, ?> join) {
return !(join instanceof org.hibernate.query.sqm.tree.spi.domain.SqmPluralPartJoin);
} Try / catch
try {
join.on(predicate);
} catch (UnsupportedOperationException e) {
// plural-part join: move the restriction to the WHERE clause instead
predicates.add(predicate);
} Prevention
- Apply ON/WITH clauses only to entity-association joins, never to element()/index()/keys() paths
- Prefer WHERE restrictions over ON when joining element collections
- In generic join-building code, test the SqmJoin type before calling on()
When it happens
Trigger: Calling jakarta.persistence.criteria.Join.on(Expression) or Join.on(String) on a Join whose referenced path source is a collection part obtained via element()/index()/keys(); HQL of the shape 'join p.nicknames.element n on ...'; any direct call to SqmJoin.setJoinPredicate(...) on an SqmPluralPartJoin instance.
Common situations: Migrating Hibernate 5 HQL that used 'with'/'on' clauses over collection elements; criteria API code that uniformly applies on() to every join it creates; switching an explicit attribute join to an element()/index() path and keeping the ON clause.
Related errors
- Attribute '{attribute}' is not joinable
- Could not interpret attribute '%s' of basic-valued path '%s'
- Boolean expression does not support max()
- Boolean expression does not support min()
- Cte root does not have an entity type. Use getReferencedPath
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/3e605de3eaf95348.
Report an issue: GitHub.