hibernate/hibernate-orm · error · MappingException

Could not instantiate comparator class [{}] for collection {

Error message

Could not instantiate comparator class [{}] for collection {}

What it means

Sorted collections configured with an explicit comparator (hbm sort="comparatorClass" or @SortComparator) are instantiated reflectively via getConstructor().newInstance(); any failure — missing public no-arg constructor, non-public class, or a constructor that throws — aborts mapping validation with this MappingException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/mapping/Collection.java:256

		return collectionTable;
	}

	public void setCollectionTable(Table table) {
		this.collectionTable = table;
	}

	public boolean isSorted() {
		return sorted;
	}

	public Comparator<?> getComparator() {
		if ( comparator == null && comparatorClassName != null ) {
			final var clazz = classForName( Comparator.class, comparatorClassName, getBootstrapContext() );
			try {
				comparator = clazz.getConstructor().newInstance();
			}
			catch (Exception e) {
				throw new MappingException( "Could not instantiate comparator class ["
						+ comparatorClassName + "] for collection " + getRole() );
			}
		}
		return comparator;
	}

	@Override
	public boolean isLazy() {
		return lazy;
	}

	@Override
	public void setLazy(boolean lazy) {
		this.lazy = lazy;
	}

	public String getRole() {
		return role;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add a public no-arg constructor to the comparator class and keep the class public.
  2. Never throw from the comparator constructor; initialize lazily inside compare().
  3. For natural ordering use @SortNatural (or omit the comparator) instead.

Example fix

// before
public class InvoiceComparator implements Comparator<Invoice> {
    public InvoiceComparator(SortService svc) { ... } // only constructor
}

// after
public class InvoiceComparator implements Comparator<Invoice> {
    public InvoiceComparator() { }
    @Override
    public int compare(Invoice a, Invoice b) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

// fail fast before building the SessionFactory
Class<? extends Comparator<?>> c = MyComparator.class;
c.getConstructor().newInstance(); // must not throw

Prevention

When it happens

Trigger: @SortComparator(InvoiceComparator.class) where the comparator has only parameterized constructors or throws from its no-arg constructor; hbm sort FQCN resolving to a non-public class; comparator constructor depending on injected or uninitialized state.

Common situations: Comparators written as DI beans or with required constructor arguments; utility comparators with hidden constructors; refactoring introducing stateful comparators.

Related errors


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