hibernate/hibernate-orm · error · UnsupportedOperationException
CollectionPersister used for [{}] does not support SQL AST
Error message
CollectionPersister used for [{}] does not support SQL AST What it means
CollectionPersister#getAttributeMapping is a default method that throws UnsupportedOperationException unless the persister implements SQL AST support. Only the AbstractCollectionPersister family (AbstractCollectionPersister/BasicCollectionPersister/OneToManyPersister) provides real mappings; a custom or legacy persister that implements the interface directly (or delegates the default) fails as soon as any SQL AST machinery needs the attribute mapping.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/persister/collection/CollectionPersister.java:111
*
* @author Gavin King
*/
public interface CollectionPersister extends Restrictable {
/**
* The NavigableRole for this collection.
*/
NavigableRole getNavigableRole();
/**
* Get the name of this collection role (the fully qualified class name,
* extended by a "property path")
*/
default String getRole() {
return getNavigableRole().getFullPath();
}
default PluralAttributeMapping getAttributeMapping() {
throw new UnsupportedOperationException( "CollectionPersister used for [" + getRole() + "] does not support SQL AST" );
}
/**
* Decomposes a collection recreate action into planned operations.
*/
void decompose(
CollectionRecreateAction action,
int ordinalBase,
SharedSessionContractImplementor session,
DecompositionContext decompositionContext,
Consumer<FlushOperation> operationConsumer);
/**
* Removes the collection:<ul>
* <li>
* For collections with a collection-table, this will execute a DELETE based
* on the {@linkplain org.hibernate.engine.spi.CollectionKey collection-key}
* </li>View on GitHub (pinned to fad1729dce)
Solutions
- Rebase the custom persister on AbstractCollectionPersister (or OneToManyPersister/BasicCollectionPersister) so attribute mappings come for free
- Override getAttributeMapping() (and the other SQL AST defaults: filters, entity graph, decompose) in the custom persister with real implementations
- Route queries/loads for such collections through APIs that do not require the SQL AST mapping (native SQL, custom loaders)
Example fix
// before
class ArchiveCollectionPersister implements CollectionPersister {
// interface implemented directly; getAttributeMapping() default throws
}
// after
class ArchiveCollectionPersister extends BasicCollectionPersister {
// inherits getAttributeMapping() and SQL AST support from AbstractCollectionPersister
} Defensive patterns
Strategy: type-guard
Type guard
// Before any SQL AST use of a collection role, confirm the persister supports it
static boolean supportsSqlAst(CollectionPersister p) {
return p instanceof org.hibernate.persister.collection.AbstractCollectionPersister;
}
// usage
if (!supportsSqlAst(persister)) {
// skip criteria/entity-graph/mutation planning; fall back to native SQL or legacy loaders
} Try / catch
try {
return persister.getAttributeMapping();
} catch (UnsupportedOperationException e) {
if (e.getMessage() != null && e.getMessage().contains("does not support SQL AST")) {
// custom persister without SQL AST support — route this role through non-SQL-AST loading
return null;
}
throw e;
} Prevention
- Base every custom CollectionPersister on AbstractCollectionPersister/Basic/OneToMany, never on the bare interface
- After a Hibernate major upgrade, smoke-test criteria/HQL over every collection role backed by custom persisters
- Treat UnsupportedOperationException on default interface methods as a build-time signal: add an integration test that walks getAttributeMapping() for each custom persister
When it happens
Trigger: A custom CollectionPersister implementation that does not extend AbstractCollectionPersister is used with APIs that call getAttributeMapping(): criteria/HQL paths over the collection, entity graph application, mutation query planning, or SQM-to-SQL translation touching the role.
Common situations: Legacy integrations with hand-rolled persisters upgraded to Hibernate 6+, where the interface gained SQL AST default methods; test doubles / mocks for persisters passed into runtime paths; custom sharding or archive persisters built before the SQL AST rewrite.
Related errors
- Could not find table group for: %s
- removeTableGroupJoin not supported by %s
- Mutating table reference should be handled by the statement
- #buildNamedQueryRepository should not be called on InFlightM
- Bootstrap registry should only contain provided services
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/9132386689867d75.
Report an issue: GitHub.