{"record":{"id":"fe7e2b9a01fdf2c0","repo":"hibernate/hibernate-orm","slug":"could-not-instantiate-comparator-class-for-co","errorCode":null,"errorMessage":"Could not instantiate comparator class [{}] for collection {}","messagePattern":"Could not instantiate comparator class \\[(.+?)\\] for collection (.+?)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/mapping/Collection.java","lineNumber":256,"sourceCode":"\t\treturn collectionTable;\n\t}\n\n\tpublic void setCollectionTable(Table table) {\n\t\tthis.collectionTable = table;\n\t}\n\n\tpublic boolean isSorted() {\n\t\treturn sorted;\n\t}\n\n\tpublic Comparator<?> getComparator() {\n\t\tif ( comparator == null && comparatorClassName != null ) {\n\t\t\tfinal var clazz = classForName( Comparator.class, comparatorClassName, getBootstrapContext() );\n\t\t\ttry {\n\t\t\t\tcomparator = clazz.getConstructor().newInstance();\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tthrow new MappingException( \"Could not instantiate comparator class [\"\n\t\t\t\t\t\t+ comparatorClassName + \"] for collection \" + getRole() );\n\t\t\t}\n\t\t}\n\t\treturn comparator;\n\t}\n\n\t@Override\n\tpublic boolean isLazy() {\n\t\treturn lazy;\n\t}\n\n\t@Override\n\tpublic void setLazy(boolean lazy) {\n\t\tthis.lazy = lazy;\n\t}\n\n\tpublic String getRole() {\n\t\treturn role;","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/mapping/Collection.java#L238-L274","documentation":"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.","triggerScenarios":"@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.","commonSituations":"Comparators written as DI beans or with required constructor arguments; utility comparators with hidden constructors; refactoring introducing stateful comparators.","solutions":["Add a public no-arg constructor to the comparator class and keep the class public.","Never throw from the comparator constructor; initialize lazily inside compare().","For natural ordering use @SortNatural (or omit the comparator) instead."],"exampleFix":"// before\npublic class InvoiceComparator implements Comparator<Invoice> {\n    public InvoiceComparator(SortService svc) { ... } // only constructor\n}\n\n// after\npublic class InvoiceComparator implements Comparator<Invoice> {\n    public InvoiceComparator() { }\n    @Override\n    public int compare(Invoice a, Invoice b) { ... }\n}","handlingStrategy":"validation","validationCode":"// fail fast before building the SessionFactory\nClass<? extends Comparator<?>> c = MyComparator.class;\nc.getConstructor().newInstance(); // must not throw","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always give comparators a public no-arg constructor","Prefer @SortNatural for natural ordering","Unit-test comparator instantiation as part of mapping tests"],"tags":["hibernate","collection","comparator","reflection"],"backgroundTag":"class-instantiation-failure","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}