hibernate/hibernate-orm · error · MappingException
No column with logical name '{}' in table '{}'
Error message
No column with logical name '{}' in table '{}' What it means
Hibernate resolves column names through a two-level model: each mapped column registers a LOGICAL name, and physical names are derived later by the naming strategy. Here getPhysicalColumnName(table, logicalReferencedColumnName) found no registered logical column with that name in the given table, and the helper rethrows a plain MappingException. It usually means the name you passed is the physical/database name, or the logical registration differs from what the mapping assumes.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java:401
private static Table table(Object persistentClassOrJoin) {
if ( persistentClassOrJoin instanceof PersistentClass persistentClass ) {
return persistentClass.getTable();
}
else if ( persistentClassOrJoin instanceof Join join ) {
return join.getTable();
}
else {
throw new IllegalArgumentException( "Unexpected object" );
}
}
private static Column column(MetadataBuildingContext context, Table table, String logicalReferencedColumnName) {
try {
return new Column( context.getMetadataCollector()
.getPhysicalColumnName( table, logicalReferencedColumnName ) );
}
catch ( MappingException me ) {
throw new MappingException( "No column with logical name '" + logicalReferencedColumnName
+ "' in table '" + table.getName() + "'" );
}
}
String buildDefaultColumnName(PersistentClass referencedEntity, String logicalReferencedColumn) {
final var context = getBuildingContext();
final var options = context.getBuildingOptions();
final var collector = context.getMetadataCollector();
final var database = collector.getDatabase();
final var jdbcEnvironment = database.getJdbcEnvironment();
final Identifier columnIdentifier = columnIdentifier(
referencedEntity,
logicalReferencedColumn,
options.getImplicitNamingStrategy(),
collector,
database
);
return options.getPhysicalNamingStrategy()View on GitHub (pinned to fad1729dce)
Solutions
- Use the LOGICAL (pre-strategy, as-written-in-mapping) name in referencedColumnName/ordering references, not the transformed physical name.
- Check your ImplicitNamingStrategy/PhysicalNamingStrategy beans: reproduce the transformation to see what logical name the target column was registered under.
- Search for duplicate mappings of the table named in the message and consolidate them.
Example fix
// before // DB column is CUST_NO; entity maps @Column(name = "CUST_NO") @JoinColumn(name = "customer_no", referencedColumnName = "cust_no") // physical name -> resolution fails // after @JoinColumn(name = "customer_no", referencedColumnName = "CUST_NO") // exactly the mapped @Column name
Defensive patterns
Strategy: validation
Validate before calling
// Guard: referenced names must equal the LOGICAL name as written in @Column
String referenced = "cust_no";
boolean matches = Arrays.stream(Target.class.getDeclaredFields())
.map(f -> { Column c = f.getAnnotation(Column.class);
return c == null || c.name().isEmpty() ? f.getName() : c.name(); })
.anyMatch(referenced::equals);
if (!matches) throw new IllegalStateException(
"'" + referenced + "' is not a logical column name of " + Target.class.getName()); Try / catch
try {
Metadata md = sources.buildMetadata();
} catch (MappingException e) {
// 'No column with logical name ... in table ...' -> referenced name differs from
// the logical name; fix it or check the naming strategy transformation
throw newConfigurationException("Logical column name mismatch", e);
} Prevention
- Reference columns exactly as they appear in the owning mapping's @Column(name=...), before any naming strategy transforms.
- Unit-test custom Implicit/PhysicalNamingStrategy beans against a known entity set.
- Avoid mapping the same table from multiple entities with different column names.
When it happens
Trigger: referencedColumnName or ordering logic supplies a physical name produced by a custom PhysicalNamingStrategy/ImplicitNamingStrategy that differs from the logical name; two mappings claim the same table with different logical names; referencing a column of a table mapped through a @Formula or secondary table where no logical name was registered.
Common situations: Custom naming strategies (snake_case conversions, prefixing) applied after mappings were written with physical names; entity A joining to a column of entity B by its DB name while B registered the logical Java-derived name; duplicate/conflicting mappings of one table across entities or XML + annotations.
Related errors
- A '@JoinColumn' references a column named '{}' but the targe
- Column '{}' is duplicated in mapping for {} (use '@Column(in
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/0276444f62726d49.
Report an issue: GitHub.