hibernate/hibernate-orm · error · UnsupportedOperationException

CollectionPersister used for

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.

Solutions

  1. Rebase the custom persister on AbstractCollectionPersister (or OneToManyPersister/BasicCollectionPersister) so attribute mappings come for free
  2. Override getAttributeMapping() (and the other SQL AST defaults: filters, entity graph, decompose) in the custom persister with real implementations
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/9132386689867d75. Report an issue: GitHub.

Appendix: 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)