hibernate/hibernate-orm · error · AnnotationException

One to many association '<propertyName>' was annotated '@Col

Error message

One to many association '<propertyName>' was annotated '@Collate'

What it means

@Collate assigns a collation to the mapped columns of an attribute. CollateBinder iterates value.getColumns(), but a @OneToMany association has no column on the owning side (the foreign key lives in the target table), so Hibernate 6.5+ rejects the annotation immediately with an AnnotationException instead of silently ignoring it.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/binder/internal/CollateBinder.java:28

import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Value;

/**
 * Handles {@link Collate} annotations.
 *
 * @author Gavin King
 */
public class CollateBinder implements AttributeBinder<Collate> {
	@Override
	public void bind(Collate collate, MetadataBuildingContext context, PersistentClass entity, Property property) {
		final Value value = property.getValue();
		if ( value instanceof OneToMany ) {
			throw new AnnotationException( "One to many association '" + property.getName()
					+ "' was annotated '@Collate'");
		}
		else if ( value instanceof Collection ) {
			throw new AnnotationException( "Collection '" + property.getName()
					+ "' was annotated '@Collate'");

		}
		else {
			for ( Column column : value.getColumns() ) {
				column.setCollation( collate.value() );
			}
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove @Collate from the @OneToMany property.
  2. To affect a real column, annotate the basic attribute that owns it, or the @ManyToOne side's join column via @Collate / @JoinColumn(columnDefinition = ...).
  3. Set collation at the database level (table/column default) if it must apply to the FK column.

Example fix

// before
@Entity
public class Customer {
    @Collate("und-x-icu")
    @OneToMany(mappedBy = "customer")
    private List<Order> orders;
}

// after
@Entity
public class Customer {
    @OneToMany(mappedBy = "customer")
    private List<Order> orders;
}

// collation only on real columns:
@Entity
public class Order {
    @Collate("und-x-icu")
    @Column(name = "code")
    private String code;
}
Defensive patterns

Strategy: validation

Validate before calling

for (Field f : cls.getDeclaredFields()) {
    boolean association = f.isAnnotationPresent(jakarta.persistence.OneToMany.class)
            || f.isAnnotationPresent(jakarta.persistence.ManyToMany.class)
            || java.util.Collection.class.isAssignableFrom(f.getType());
    if (f.isAnnotationPresent(org.hibernate.annotations.Collate.class) && association) {
        throw new IllegalStateException("@Collate not allowed on collections: " + f.getName());
    }
}

Try / catch

Catch org.hibernate.AnnotationException during bootstrap; the message names the property. Report as a mapping defect and stop.

Prevention

When it happens

Trigger: @Collate on a property mapped as @OneToMany (bidirectional mappedBy or unidirectional with @JoinColumn); the attribute binder sees a OneToMany value and throws before any column processing.

Common situations: Blanket-applying @Collate to all textual attributes including associations; attempting to control FK column collation from the parent side of the association; migrating columnDefinition strings to @Collate and hitting association properties.

Related errors


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