hibernate/hibernate-orm · error · MappingException
Foreign key ({}:{} [{}])) must have same number of columns a
Error message
Foreign key ({}:{} [{}])) must have same number of columns as the referenced primary key ({} [{}]) What it means
ForeignKey#alignColumns validates that a foreign key referencing the target primary key has exactly as many columns as that PK. A mismatch means the composite join does not line up with the referenced composite key, so Hibernate aborts before generating a broken FK, while also using the check to align column length/scale/precision.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/mapping/ForeignKey.java:88
}
}
}
public void setReferencedTable(Table referencedTable) throws MappingException {
this.referencedTable = referencedTable;
}
/**
* Validates that column span of the foreign key and the primary key is the same.
* <p>
* Furthermore it aligns the length of the underlying tables columns.
*/
public void alignColumns() {
if ( isReferenceToPrimaryKey() ) {
final int columnSpan = getColumnSpan();
final var primaryKey = referencedTable.getPrimaryKey();
if ( primaryKey.getColumnSpan() != columnSpan ) {
throw new MappingException( unalignedColumnsMessage( primaryKey ) );
}
//TODO: shouldn't this happen even for non-PK references?
for ( int i = 0; i<columnSpan; i++ ) {
final var referencedColumn = primaryKey.getColumn(i);
final var referencingColumn = getColumn(i);
referencingColumn.setLength( referencedColumn.getLength() );
referencingColumn.setScale( referencedColumn.getScale() );
referencingColumn.setPrecision( referencedColumn.getPrecision() );
referencingColumn.setArrayLength( referencedColumn.getArrayLength() );
}
}
}
private String unalignedColumnsMessage(PrimaryKey primaryKey) {
final var message = new StringBuilder();
message.append( "Foreign key (" ).append( getName() ).append( ":" )
.append( getTable().getName() )View on GitHub (pinned to fad1729dce)
Solutions
- Declare one @JoinColumn per referenced PK column, each with an explicit referencedColumnName matching the PK column names.
- If the parent PK changed, update every child mapping's join columns in the same change.
- Check for accidentally duplicated or missing @JoinColumn annotations and align their order with the PK.
Example fix
// before - parent PK is composite (a, b)
@Id
@ManyToOne
@JoinColumn(name = "a")
private Parent parent;
// after
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name = "a", referencedColumnName = "a"),
@JoinColumn(name = "b", referencedColumnName = "b")
})
private Parent parent; Defensive patterns
Strategy: try-catch
Try / catch
try {
metadata = sources.buildMetadata();
} catch (MappingException e) {
// message prints both key column lists - diff them to find the
// missing or extra join column on the referencing side
throw e;
} Prevention
- For composite PKs always use @JoinColumns with explicit referencedColumnName - never rely on defaults.
- When adding a PK column, grep mappings for associations to that entity and update the join columns.
- Run SchemaValidator or create-drop in CI to catch FK span mismatches before deployment.
When it happens
Trigger: The target has a composite @EmbeddedId while the referencing side declares fewer @JoinColumn entries; the parent PK gained a column but child mappings were not updated; @JoinColumn entries referencing only part of the composite PK; column ordering changed inside @Embeddable.
Common situations: Evolving composite keys; hand-written @JoinColumn(name=...) without referencedColumnName; switching between @IdClass and @EmbeddedId; database refactors adding PK columns.
Related errors
- Attribute '%s' of entity '%s' is mapped by association '%s'
- Identity generation requires exactly one column
- Number of referencing columns [%s] did not match number of r
- Identifier property '" + getPath( holder, data ) + "' cannot
- Identifier attribute '%s' of entity '%s' has type '%s' but i
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/78fa4017d1cd9a6e.
Report an issue: GitHub.