{"record":{"id":"0276444f62726d49","repo":"hibernate/hibernate-orm","slug":"no-column-with-logical-name-in-table","errorCode":null,"errorMessage":"No column with logical name '{}' in table '{}'","messagePattern":"No column with logical name '(.+?)' in table '(.+?)'","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java","lineNumber":401,"sourceCode":"\tprivate static Table table(Object persistentClassOrJoin) {\n\t\tif ( persistentClassOrJoin instanceof PersistentClass persistentClass ) {\n\t\t\treturn persistentClass.getTable();\n\t\t}\n\t\telse if ( persistentClassOrJoin instanceof Join join ) {\n\t\t\treturn join.getTable();\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException( \"Unexpected object\" );\n\t\t}\n\t}\n\n\tprivate static Column column(MetadataBuildingContext context, Table table, String logicalReferencedColumnName) {\n\t\ttry {\n\t\t\treturn new Column( context.getMetadataCollector()\n\t\t\t\t\t.getPhysicalColumnName( table, logicalReferencedColumnName ) );\n\t\t}\n\t\tcatch ( MappingException me ) {\n\t\t\tthrow new MappingException( \"No column with logical name '\" + logicalReferencedColumnName\n\t\t\t\t\t+ \"' in table '\" + table.getName() + \"'\" );\n\t\t}\n\t}\n\n\tString buildDefaultColumnName(PersistentClass referencedEntity, String logicalReferencedColumn) {\n\t\tfinal var context = getBuildingContext();\n\t\tfinal var options = context.getBuildingOptions();\n\t\tfinal var collector = context.getMetadataCollector();\n\t\tfinal var database = collector.getDatabase();\n\t\tfinal var jdbcEnvironment = database.getJdbcEnvironment();\n\t\tfinal Identifier columnIdentifier = columnIdentifier(\n\t\t\t\treferencedEntity,\n\t\t\t\tlogicalReferencedColumn,\n\t\t\t\toptions.getImplicitNamingStrategy(),\n\t\t\t\tcollector,\n\t\t\t\tdatabase\n\t\t);\n\t\treturn options.getPhysicalNamingStrategy()","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java#L383-L419","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n// DB column is CUST_NO; entity maps @Column(name = \"CUST_NO\")\n@JoinColumn(name = \"customer_no\", referencedColumnName = \"cust_no\") // physical name -> resolution fails\n\n// after\n@JoinColumn(name = \"customer_no\", referencedColumnName = \"CUST_NO\") // exactly the mapped @Column name","handlingStrategy":"validation","validationCode":"// Guard: referenced names must equal the LOGICAL name as written in @Column\nString referenced = \"cust_no\";\nboolean matches = Arrays.stream(Target.class.getDeclaredFields())\n    .map(f -> { Column c = f.getAnnotation(Column.class);\n                return c == null || c.name().isEmpty() ? f.getName() : c.name(); })\n    .anyMatch(referenced::equals);\nif (!matches) throw new IllegalStateException(\n    \"'\" + referenced + \"' is not a logical column name of \" + Target.class.getName());","typeGuard":null,"tryCatchPattern":"try {\n    Metadata md = sources.buildMetadata();\n} catch (MappingException e) {\n    // 'No column with logical name ... in table ...' -> referenced name differs from\n    // the logical name; fix it or check the naming strategy transformation\n    throw newConfigurationException(\"Logical column name mismatch\", e);\n}","preventionTips":["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."],"tags":["hibernate","naming-strategy","logical-name","join-column","orm-mapping"],"backgroundTag":"logical-column-name-resolution","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}