hibernate/hibernate-orm · error · AnnotationException
Property '${property}' is annotated '@OrderBy' but is not of
Error message
Property '${property}' is annotated '@OrderBy' but is not of type 'Collection' or 'Map' What it means
@OrderBy specifies in-memory ordering of a collection or map at load time, so JPA only allows it on attributes whose type implements Collection or Map. PropertyBinder validates this during metadata building and throws AnnotationException when the annotated property is a basic type, embedded, or single-valued association.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java:653
final String options =
isBlank( existing )
? exclusion
: existing + " " + exclusion;
column.setOptions( options );
}
}
}
}
private void validateAnnotationsAgainstType() {
if ( memberDetails != null ) {
final var type = memberDetails.getType();
if ( !(type instanceof ArrayTypeDetails) ) {
checkAnnotation( OrderColumn.class, List.class );
if ( memberDetails.hasDirectAnnotationUsage( OrderBy.class )
&& !type.isImplementor( Collection.class )
&& !type.isImplementor( Map.class ) ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
+ "' is annotated '@OrderBy' but is not of type 'Collection' or 'Map'" );
}
}
checkAnnotation( MapKey.class, Map.class );
checkAnnotation( MapKeyColumn.class, Map.class );
checkAnnotation( MapKeyClass.class, Map.class );
checkAnnotation( MapKeyEnumerated.class, Map.class );
checkAnnotation( MapKeyTemporal.class, Map.class );
checkAnnotation( MapKeyColumn.class, Map.class );
checkAnnotation( MapKeyJoinColumn.class, Map.class );
checkAnnotation( MapKeyJoinColumns.class, Map.class );
}
}
private void checkAnnotation(Class<? extends Annotation> annotationClass, Class<?> propertyType) {
if ( memberDetails.hasDirectAnnotationUsage( annotationClass )
&& !memberDetails.getType().isImplementor( propertyType ) ) {
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )View on GitHub (pinned to fad1729dce)
Solutions
- Remove @OrderBy — the property is not orderable.
- If ordering was intended, the property should be a List/Set/Collection (or Map) of elements.
- For ordering single results there is nothing to order: rely on query-level ORDER BY in JPQL/Criteria instead.
Example fix
// before
@OrderBy("createdAt")
private Comment comment; // single-valued => rejected
// after (choose one)
// 1) it should be a collection:
@OrderBy("createdAt")
private List<Comment> comments = new ArrayList<>();
// 2) it really is single-valued: delete the @OrderBy and sort in queries Defensive patterns
Strategy: validation
Validate before calling
// Guard @OrderBy against non-collection/non-map properties before boot
for (Class<?> entity : annotatedClasses) {
for (Field f : entity.getDeclaredFields()) {
if (f.isAnnotationPresent(OrderBy.class)
&& !(Collection.class.isAssignableFrom(f.getType()) || Map.class.isAssignableFrom(f.getType()))) {
throw new IllegalStateException("@OrderBy on non-collection field " + f);
}
}
} Type guard
static boolean supportsOrderBy(Class<?> propertyType) {
return Collection.class.isAssignableFrom(propertyType) || Map.class.isAssignableFrom(propertyType);
} Try / catch
try {
SessionFactory sf = cfg.buildSessionFactory();
} catch (AnnotationException e) {
throw new IllegalStateException("Collection annotation misuse: " + e.getMessage(), e);
} Prevention
- When changing a field from collection to single-valued (or back), sweep the field for collection-only annotations
- Keep a lint/review checklist: @OrderBy => Collection/Map
When it happens
Trigger: @OrderBy("email") on a scalar field like private String email; @OrderBy on a single @OneToOne/@ManyToOne association; @OrderBy on an embeddable attribute; code migrated from a collection to a single value (e.g. List<Line> collapsed to Line) with the annotation left behind.
Common situations: Changing a field's type during refactoring (collection to single object) without cleaning annotations; copy-paste of collection annotations onto new scalar fields; generated code from templates targeting collections.
Related errors
- Property '${property}' is annotated '@${annotation}' but is
- Member '" + memberDetails.getName() + "' of embeddable class
- AttributeConverter class [%s] registered multiple times
- Duplicate named query '%s'
- Duplicate named stored procedure '{}'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/024ce12188c366c1.
Report an issue: GitHub.