{"record":{"id":"1eaba6b136a8aa16","repo":"hibernate/hibernate-orm","slug":"association-path-is-mappedby-a-property-nam","errorCode":null,"errorMessage":"Association '${path}' is 'mappedBy' a property named '${mappedBy}' of the target entity type '${type}' which is not a '@OneToOne' or '@ManyToOne' association","messagePattern":"Association '(.+?)' is 'mappedBy' a property named '(.+?)' of the target entity type '(.+?)' which is not a '@OneToOne' or '@ManyToOne' association","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/OneToOneSecondPass.java","lineNumber":100,"sourceCode":"\n\tprivate void bindUnowned(Map<String, PersistentClass> persistentClasses, OneToOne oneToOne) {\n\t\toneToOne.setMappedByProperty( mappedBy );\n\t\tfinal String targetEntityName = oneToOne.getReferencedEntityName();\n\t\tfinal var targetEntity = persistentClasses.get( targetEntityName );\n\t\tif ( targetEntity == null ) {\n\t\t\tfinal String problem = annotatedEntity\n\t\t\t\t\t? \" which does not belong to the same persistence unit\"\n\t\t\t\t\t: \" which is not an '@Entity' type\";\n\t\t\tthrow new MappingException( \"Association '\" + getPath( propertyHolder, inferredData )\n\t\t\t\t\t+ \"' targets the type '\" + targetEntityName + \"'\" + problem );\n\t\t}\n\t\tfinal var targetProperty = targetProperty( oneToOne, targetEntity );\n\t\tfinal var targetPropertyValue = targetProperty.getValue();\n\t\tif ( targetPropertyValue instanceof ManyToOne ) {\n\t\t\tbindTargetManyToOne( persistentClasses, oneToOne, targetEntity, targetProperty );\n\t\t}\n\t\telse if ( !(targetPropertyValue instanceof OneToOne) ) {\n\t\t\tthrow new AnnotationException( \"Association '\" + getPath( propertyHolder, inferredData )\n\t\t\t\t\t+ \"' is 'mappedBy' a property named '\" + mappedBy\n\t\t\t\t\t+ \"' of the target entity type '\" + targetEntityName\n\t\t\t\t\t+ \"' which is not a '@OneToOne' or '@ManyToOne' association\" );\n\t\t}\n\t\tcheckMappedByType(\n\t\t\t\tmappedBy,\n\t\t\t\ttargetPropertyValue,\n\t\t\t\toneToOne.getPropertyName(),\n\t\t\t\tpropertyHolder,\n\t\t\t\tpersistentClasses\n\t\t);\n\t}\n\n\tprivate void bindTargetManyToOne(\n\t\t\tMap<String, PersistentClass> persistentClasses,\n\t\t\tOneToOne oneToOne,\n\t\t\tPersistentClass targetEntity,\n\t\t\tProperty targetProperty) {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/OneToOneSecondPass.java#L82-L118","documentation":"For the non-owning (mappedBy) side of a @OneToOne, Hibernate inspects the property named by 'mappedBy' on the target entity. That property exists but its value is neither a @OneToOne nor a @ManyToOne, so there is no valid owning side to map back to, and AnnotationException is thrown during second-pass binding.","triggerScenarios":"@OneToOne(mappedBy = \"profile\") where Profile.profile exists but is a plain attribute, a @OneToMany, or an @Embedded; also when the owning side was annotated with the wrong cardinality (e.g. @OneToMany instead of @ManyToOne) so the inverse lookup finds a non-conforming value.","commonSituations":"Building a bidirectional one-to-one and annotating the wrong side as owner; copy-pasting a one-to-many pattern into a one-to-one; renaming/re-typing the owning property during refactoring while leaving mappedBy pointing at a now-basic field.","solutions":["Annotate the mappedBy-referenced property on the target entity with @OneToOne (or @ManyToOne) so it becomes a valid owning side.","Double-check which side owns the foreign key: the side WITHOUT mappedBy gets @JoinColumn; the inverse side gets mappedBy.","If the target property is genuinely not an association, the mappedBy value is wrong — point it at the actual owning property name (see also the 'does not exist' variant of this error)."],"exampleFix":"// before: owning side is not an association\npublic class User {\n    @OneToOne(mappedBy = \"user\")\n    private Profile profile;\n}\npublic class Profile {\n    private User user;   // no annotation => not an owning side\n}\n\n// after\npublic class Profile {\n    @OneToOne(fetch = FetchType.LAZY)\n    @JoinColumn(name = \"user_id\")\n    private User user;\n}","handlingStrategy":"validation","validationCode":"// Check the mappedBy target property is an association of allowed kind\nfor (Class<?> entity : annotatedClasses) {\n    for (Field f : entity.getDeclaredFields()) {\n        OneToOne o2o = f.getAnnotation(OneToOne.class);\n        if (o2o == null || o2o.mappedBy().isEmpty()) continue;\n        Field inverse = f.getType().getDeclaredField(o2o.mappedBy());\n        if (inverse.getAnnotation(OneToOne.class) == null && inverse.getAnnotation(ManyToOne.class) == null) {\n            throw new IllegalStateException(\"mappedBy '\" + o2o.mappedBy() + \"' on \" + f + \" is not @OneToOne/@ManyToOne\");\n        }\n    }\n}","typeGuard":"static boolean isValidOwningSide(Field f) {\n    return f.isAnnotationPresent(OneToOne.class) || f.isAnnotationPresent(ManyToOne.class);\n}","tryCatchPattern":"try {\n    SessionFactory sf = cfg.buildSessionFactory();\n} catch (AnnotationException e) {\n    throw new IllegalStateException(\"Bidirectional mapping broken: \" + e.getMessage(), e);\n}","preventionTips":["Put @JoinColumn on the owning side and mappedBy on the inverse — never both","Write one integration test per bidirectional relationship that boots the factory"],"tags":["hibernate","jpa","one-to-one","mappedby","association","bootstrap"],"backgroundTag":"mappedby-mapping-error","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}