{"record":{"id":"3242f8be5a1cb59e","repo":"hibernate/hibernate-orm","slug":"association-s-is-mappedby-a-property-s-of-3242f8","errorCode":null,"errorMessage":"Association '%s' is 'mappedBy' a property '%s' of entity '%s' which maps to a formula","messagePattern":"Association '(.+?)' is 'mappedBy' a property '(.+?)' of entity '(.+?)' which maps to a formula","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java","lineNumber":619,"sourceCode":"\t\t\t}\n\n\t\t\tfinal var mappedByProperty =\n\t\t\t\t\tcollector.getEntityBinding( getMappedByEntityName() )\n\t\t\t\t\t\t\t.getProperty( getMappedByPropertyName() );\n\t\t\tfinal var value = (SimpleValue) mappedByProperty.getValue();\n\t\t\tif ( value.getSelectables().isEmpty() ) {\n\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\tLocale.ENGLISH,\n\t\t\t\t\t\t\t\t\"Association '%s' is 'mappedBy' a property '%s' of entity '%s' with no columns\",\n\t\t\t\t\t\t\t\tgetPropertyHolder().getPath(),\n\t\t\t\t\t\t\t\tgetMappedByPropertyName(),\n\t\t\t\t\t\t\t\tgetMappedByEntityName()\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif ( !(value.getSelectables().get( 0 ) instanceof Column column) ) {\n\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\tLocale.ENGLISH,\n\t\t\t\t\t\t\t\t\"Association '%s' is 'mappedBy' a property '%s' of entity '%s' which maps to a formula\",\n\t\t\t\t\t\t\t\tgetPropertyHolder().getPath(),\n\t\t\t\t\t\t\t\tgetMappedByPropertyName(),\n\t\t\t\t\t\t\t\tgetPropertyHolder().getPath()\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif ( value.getSelectables().size() > 1 ) {\n\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\tLocale.ENGLISH,\n\t\t\t\t\t\t\t\t\"Association '%s' is 'mappedBy' a property '%s' of entity '%s' with multiple columns\",\n\t\t\t\t\t\t\t\tgetPropertyHolder().getPath(),\n\t\t\t\t\t\t\t\tgetMappedByPropertyName(),\n\t\t\t\t\t\t\t\tgetPropertyHolder().getPath()\n\t\t\t\t\t\t)","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java#L601-L637","documentation":"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.)","triggerScenarios":"'@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.","commonSituations":"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.","solutions":["Replace the @JoinFormula/@Formula on the owning side with a real @JoinColumn so a physical column backs the association.","If the formula join is mandatory, drop mappedBy and map the collection with an explicit @JoinTable or leave it unidirectional.","Re-check that mappedBy targets the association property, not a separate formula-mapped attribute."],"exampleFix":"// before\n@Entity\nclass Team {\n    @ManyToOne\n    @JoinColumnOrFormula(formula = @JoinFormula(value = \"upper(code)\", referencedColumnName = \"code\"))\n    League league; // formula, not a column\n}\n\n@Entity\nclass League {\n    @OneToMany(mappedBy = \"league\") // -> error: mapped by a formula\n    List<Team> teams;\n}\n\n// after\n@Entity\nclass Team {\n    @ManyToOne(fetch = FetchType.LAZY)\n    @JoinColumn(name = \"league_code\", referencedColumnName = \"code\")\n    League league;\n}","handlingStrategy":"validation","validationCode":"// Guard: the mappedBy owner must not be formula-backed\nString mappedBy = \"league\";\nField owner = Team.class.getDeclaredField(mappedBy);\nif (owner.getAnnotation(JoinFormula.class) != null\n        || Arrays.stream(owner.getAnnotationsByType(JoinColumnOrFormula.class))\n                 .anyMatch(j -> j.formula() != null && !j.formula().value().isEmpty())) {\n    throw new IllegalStateException(\"mappedBy owner '\" + mappedBy + \"' is formula-backed\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    factory = cfg.buildSessionFactory();\n} catch (AnnotationException e) {\n    // 'which maps to a formula' -> replace the @JoinFormula with a real\n    // @JoinColumn or map the collection via @JoinTable\n    throw newConfigurationException(\"Formula-backed mappedBy\", e);\n}","preventionTips":["Use @JoinColumn for associations you plan to make bidirectional; reserve @JoinFormula for read-only unidirectional joins.","If a formula join is required, keep the collection side unidirectional or use an explicit join table."],"tags":["hibernate","jpa","mappedby","formula","orm-mapping"],"backgroundTag":"mappedby-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}