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

  1. Remove the @AssociationOverride (or XML <association-override>) that targets the property path shown in the message.
  2. If the override is required, change the original mapping from @JoinColumnOrFormula to plain @JoinColumn(s) so the override can apply.
  3. 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

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


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