hibernate/hibernate-orm · error · AnnotationException
Property '${path}' overrides mapping specified using '@JoinC
Error message
Property '${path}' overrides mapping specified using '@JoinColumnOrFormula' What it means
The property is part of an embedded or inherited mapping that was originally declared with '@JoinColumnOrFormula' (a mix of a real join column and a formula). Something else — typically an '@AssociationOverride' (annotation or XML) — then tries to re-map that same property path with plain join columns. Hibernate cannot override a formula-based association mapping, so it rejects the override outright (the source even carries a 'TODO: relax this restriction' note).
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java:84
/**
* @return true if the {@code @JoinColumn} annotation did not specify the
* {@link JoinColumn#referencedColumnName() referencedColumnName}.
*/
public boolean isReferenceImplicit() {
return isEmpty( referencedColumn );
}
static AnnotatedJoinColumn buildJoinColumn(
JoinColumn joinColumn,
String mappedBy,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
PropertyData inferredData) {
final String path = qualify( propertyHolder.getPath(), inferredData.getPropertyName() );
final var overrides = propertyHolder.getOverriddenJoinColumn( path );
if ( overrides != null ) {
//TODO: relax this restriction
throw new AnnotationException( "Property '" + path
+ "' overrides mapping specified using '@JoinColumnOrFormula'" );
}
return buildJoinColumn( joinColumn, mappedBy, parent, propertyHolder, inferredData, "" );
}
public static AnnotatedJoinColumn buildJoinFormula(
JoinFormula joinFormula,
AnnotatedJoinColumns parent) {
final var formulaColumn = new AnnotatedJoinColumn();
formulaColumn.setFormula( joinFormula.value() );
formulaColumn.setReferencedColumn( joinFormula.referencedColumnName() );
// formulaColumn.setContext( buildingContext );
// formulaColumn.setPropertyHolder( propertyHolder );
// formulaColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
// formulaColumn.setJoins( joins );
formulaColumn.setParent( parent );
formulaColumn.bind();
return formulaColumn;View on GitHub (pinned to fad1729dce)
Solutions
- Remove the @AssociationOverride (or XML <association-override>) that targets the property path shown in the message.
- If the override is required, change the original mapping from @JoinColumnOrFormula to plain @JoinColumn(s) so the override can apply.
- Instead of overriding, define the association directly on the concrete entity with the desired @JoinColumn mapping.
Example fix
// before
@Embeddable
class Ref {
@ManyToOne
@JoinColumnOrFormula(column = @JoinColumn(name = "item_id"))
private Item item;
}
@Entity
@AssociationOverride(name = "ref.item", joinColumns = @JoinColumn(name = "prod_item_id")) // -> error
class Product { private Ref ref; }
// after
@Entity
class Product {
@Embedded
private Ref ref; // no override; or remap Ref.item with plain @JoinColumn
} Defensive patterns
Strategy: validation
Validate before calling
// Fail fast when an override targets a formula-based association
// (inspect source embeddables before SessionFactory construction)
if (hasAssociationOverride(targetClass, "ref.item")
&& usesJoinColumnOrFormula(embeddableClass, "item")) {
throw new IllegalStateException(
"Cannot @AssociationOverride a @JoinColumnOrFormula mapping: ref.item");
} Try / catch
try {
Metadata md = new MetadataSources(registry).addAnnotatedClass(Product.class)
.buildMetadata();
} catch (AnnotationException e) {
// message shows the overridden path; remove the override or change the base mapping
throw newConfigurationException("Unsupported association override", e);
} Prevention
- Treat @JoinColumnOrFormula mappings as non-overridable; document them in the embeddable's Javadoc.
- Prefer plain @JoinColumn in shared embeddables so subclasses can override them.
- When adding @AssociationOverride, re-run a mapping test for every entity that embeds the component.
When it happens
Trigger: An @Embedded/@EmbeddedId or @MappedSuperclass declares an association with @JoinColumnOrFormula(...), and the embedding entity applies @AssociationOverride(name="<embeddable>.<assoc>", joinColumns=@JoinColumn(...)) or an XML <association-override> for that path; propertyHolder.getOverriddenJoinColumn(path) then returns a non-null override.
Common situations: Reusing a shared embeddable (e.g. a generic audit or reference component) that uses @JoinColumnOrFormula, then overriding it in a concrete entity; migrating mappings to XML and back where overrides are reapplied mechanically; Envers-style or custom embeddables with formula-based references.
Related errors
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
- Collection '<propertyName>' was annotated '@Collate'
- Root entity '<entityName>' is annotated '@DiscriminatorOptio
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/015dba83562ce272.
Report an issue: GitHub.