{"record":{"id":"2c330b1f52ea9c21","repo":"hibernate/hibernate-orm","slug":"a-joincolumn-references-a-column-named-but","errorCode":null,"errorMessage":"A '@JoinColumn' references a column named '{}' but the target entity '{}' has no property which maps to this column","messagePattern":"A '@JoinColumn' references a column named '(.+?)' but the target entity '(.+?)' has no property which maps to this column","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java","lineNumber":342,"sourceCode":"\t * Determine if the given {@link AnnotatedJoinColumns} represent a reference to\n\t * the primary key of the given {@link PersistentClass}, or whether they reference\n\t * some other combination of mapped columns.\n\t */\n\tpublic ForeignKeyType getReferencedColumnsType(PersistentClass referencedEntity) {\n\t\tif ( referencedProperty != null ) {\n\t\t\treturn NON_PRIMARY_KEY_REFERENCE;\n\t\t}\n\n\t\tif ( columns.isEmpty() ) {\n\t\t\treturn ForeignKeyType.IMPLICIT_PRIMARY_KEY_REFERENCE; //shortcut\n\t\t}\n\n\t\tfinal var firstColumn = columns.get( 0 );\n\t\tfinal var context = getBuildingContext();\n\t\tfinal Object columnOwner = findReferencedColumnOwner( referencedEntity, firstColumn, context );\n\t\tif ( columnOwner == null ) {\n\t\t\ttry {\n\t\t\t\tthrow new MappingException( \"A '@JoinColumn' references a column named '\"\n\t\t\t\t\t\t+ firstColumn.getReferencedColumn() + \"' but the target entity '\"\n\t\t\t\t\t\t+ referencedEntity.getEntityName() + \"' has no property which maps to this column\" );\n\t\t\t}\n\t\t\tcatch ( MappingException me ) {\n\t\t\t\t// we throw a recoverable exception here in case this\n\t\t\t\t// is merely an ordering issue, so that the SecondPass\n\t\t\t\t// will get reprocessed later\n\t\t\t\tthrow new FailedSecondPassException( me.getMessage(), me );\n\t\t\t}\n\t\t}\n\t\tfinal var table = table( columnOwner );\n//\t\tfinal List<Selectable> keyColumns = referencedEntity.getKey().getSelectables();\n\t\tfinal var keyColumns =\n\t\t\t\ttable.getPrimaryKey() == null\n\t\t\t\t\t\t? referencedEntity.getKey().getSelectables()\n\t\t\t\t\t\t: table.getPrimaryKey().getColumns();\n\t\tboolean explicitColumnReference = false;\n\t\tfor ( var column : columns ) {","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java#L324-L360","documentation":"A '@JoinColumn(referencedColumnName=...)' names a column on the target entity, but no property of that entity maps the column, so Hibernate cannot resolve the reference. The code deliberately rethrows it as FailedSecondPassException so the metadata collector can retry later passes in case the binding is merely out of order; if the error survives to the end of bootstrap, the reference itself is wrong.","triggerScenarios":"referencedColumnName has a typo or wrong case; the referenced column exists in the database but the target entity has no mapped property for it (no field maps that column); the target attribute is mapped by a @Formula rather than a real column; the FK targets a natural key property that was never mapped.","commonSituations":"Hand-typed referencedColumnName strings drifted from the schema; joining to a unique business column (SSN, email) that the target entity does not map as a field; databases with case-sensitive identifiers; mappings that worked when the column was the PK but broke after switching to a natural-key reference.","solutions":["Correct referencedColumnName to exactly match the mapped column of a real property on the target entity.","Add or restore the target property that maps the referenced column (e.g. a @Column(name=\"...\") field or unique @ManyToOne).","If you do not need a non-PK reference, remove referencedColumnName so the join defaults to the target's primary key."],"exampleFix":"// before\n@ManyToOne(fetch = FetchType.LAZY)\n@JoinColumn(name = \"user_email\", referencedColumnName = \"email_address\") // target maps 'email', not 'email_address'\nprivate User user;\n\n// after\n@ManyToOne(fetch = FetchType.LAZY)\n@JoinColumn(name = \"user_email\", referencedColumnName = \"email\")\nprivate User user;","handlingStrategy":"validation","validationCode":"// Guard: referencedColumnName must match a mapped column on the target entity\nClass<?> target = User.class;\nSet<String> mapped = new HashSet<>();\nfor (Field f : target.getDeclaredFields()) {\n    Column c = f.getAnnotation(Column.class);\n    if (c != null) mapped.add(c.name().isEmpty() ? f.getName() : c.name());\n}\nJoinColumn jc = orderField.getAnnotation(JoinColumn.class);\nif (jc != null && !jc.referencedColumnName().isEmpty()\n        && !mapped.contains(jc.referencedColumnName())) {\n    throw new IllegalStateException(\"referencedColumnName '\" + jc.referencedColumnName()\n        + \"' is not mapped by \" + target.getSimpleName());\n}","typeGuard":null,"tryCatchPattern":"try {\n    factory = cfg.buildSessionFactory();\n} catch (FailedSecondPassException | AnnotationException e) {\n    // Hibernate retries ordering internally; if it still fails, the reference is wrong.\n    // 'has no property which maps to this column' -> fix referencedColumnName\n    throw newConfigurationException(\"Unresolvable join column reference\", e);\n}","preventionTips":["Default to the target's primary key by omitting referencedColumnName whenever possible.","Derive referencedColumnName from a constant shared with the target's @Column declaration, never a literal.","When joining to natural keys, verify the target entity actually maps that column as a field."],"tags":["hibernate","jpa","join-column","referenced-column-name","orm-mapping"],"backgroundTag":"join-column-reference-error","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}