hibernate/hibernate-orm · error · AnnotationException

Association '%s' is 'mappedBy' a property '%s' of entity '%s

Error message

Association '%s' is 'mappedBy' a property '%s' of entity '%s' which maps to a formula

What it means

The property this association is 'mappedBy' resolves to a value whose first selectable is not a real Column but a formula (@Formula / @JoinColumnOrFormula). Hibernate needs one concrete column to derive the inverse side's join/order column, and a formula cannot serve, so the mapping is refused. (Note the message itself prints the property-holder path twice due to an upstream formatting quirk.)

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java:619

			}

			final var mappedByProperty =
					collector.getEntityBinding( getMappedByEntityName() )
							.getProperty( getMappedByPropertyName() );
			final var value = (SimpleValue) mappedByProperty.getValue();
			if ( value.getSelectables().isEmpty() ) {
				throw new AnnotationException(
						String.format(
								Locale.ENGLISH,
								"Association '%s' is 'mappedBy' a property '%s' of entity '%s' with no columns",
								getPropertyHolder().getPath(),
								getMappedByPropertyName(),
								getMappedByEntityName()
						)
				);
			}
			if ( !(value.getSelectables().get( 0 ) instanceof Column column) ) {
				throw new AnnotationException(
						String.format(
								Locale.ENGLISH,
								"Association '%s' is 'mappedBy' a property '%s' of entity '%s' which maps to a formula",
								getPropertyHolder().getPath(),
								getMappedByPropertyName(),
								getPropertyHolder().getPath()
						)
				);
			}
			if ( value.getSelectables().size() > 1 ) {
				throw new AnnotationException(
						String.format(
								Locale.ENGLISH,
								"Association '%s' is 'mappedBy' a property '%s' of entity '%s' with multiple columns",
								getPropertyHolder().getPath(),
								getMappedByPropertyName(),
								getPropertyHolder().getPath()
						)

View on GitHub (pinned to fad1729dce)

Solutions

  1. Replace the @JoinFormula/@Formula on the owning side with a real @JoinColumn so a physical column backs the association.
  2. If the formula join is mandatory, drop mappedBy and map the collection with an explicit @JoinTable or leave it unidirectional.
  3. Re-check that mappedBy targets the association property, not a separate formula-mapped attribute.

Example fix

// before
@Entity
class Team {
    @ManyToOne
    @JoinColumnOrFormula(formula = @JoinFormula(value = "upper(code)", referencedColumnName = "code"))
    League league; // formula, not a column
}

@Entity
class League {
    @OneToMany(mappedBy = "league") // -> error: mapped by a formula
    List<Team> teams;
}

// after
@Entity
class Team {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "league_code", referencedColumnName = "code")
    League league;
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard: the mappedBy owner must not be formula-backed
String mappedBy = "league";
Field owner = Team.class.getDeclaredField(mappedBy);
if (owner.getAnnotation(JoinFormula.class) != null
        || Arrays.stream(owner.getAnnotationsByType(JoinColumnOrFormula.class))
                 .anyMatch(j -> j.formula() != null && !j.formula().value().isEmpty())) {
    throw new IllegalStateException("mappedBy owner '" + mappedBy + "' is formula-backed");
}

Try / catch

try {
    factory = cfg.buildSessionFactory();
} catch (AnnotationException e) {
    // 'which maps to a formula' -> replace the @JoinFormula with a real
    // @JoinColumn or map the collection via @JoinTable
    throw newConfigurationException("Formula-backed mappedBy", e);
}

Prevention

When it happens

Trigger: '@OneToMany(mappedBy = "x")' where the owning property x is a @ManyToOne referenced through @JoinColumnOrFormula(..., formula=@JoinFormula(...)); the owning side's FK is defined with @Formula instead of @JoinColumn; legacy @org.hibernate.annotations.Formula on the mapped property.

Common situations: Joining by an expression (e.g. concatenation or computed key) and then trying to hang a mappedBy collection off it; converting a working unidirectional formula join to a bidirectional one.

Related errors


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