{"record":{"id":"66449b6057d0512c","repo":"hibernate/hibernate-orm","slug":"association-is-mappedby-another-entity-and","errorCode":null,"errorMessage":"Association '{}' is 'mappedBy' another entity and may not specify the '@JoinColumn'","messagePattern":"Association '(.+?)' is 'mappedBy' another entity and may not specify the '@JoinColumn'","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java","lineNumber":1191,"sourceCode":"\t\t\tincludeInOptimisticLockChecks = !isMappedBy;\n\t\t}\n\t\tcollection.setOptimisticLocked( includeInOptimisticLockChecks );\n\t}\n\n\tprivate void bindCache() {\n\t\t//set cache\n\t\tif ( isNotBlank( cacheConcurrencyStrategy ) ) {\n\t\t\tcollection.setCacheConcurrencyStrategy( cacheConcurrencyStrategy );\n\t\t\tcollection.setCacheRegionName( cacheRegionName );\n\t\t}\n\t\tcollection.setQueryCacheLayout( queryCacheLayout );\n\t}\n\n\tprivate void detectMappedByProblem(boolean isMappedBy) {\n\t\tif ( isMappedBy ) {\n\t\t\tif ( property.hasDirectAnnotationUsage( JoinColumn.class )\n\t\t\t\t\t|| property.hasDirectAnnotationUsage( JoinColumns.class ) ) {\n\t\t\t\tthrow new AnnotationException( \"Association '\"\n\t\t\t\t\t\t+ qualify( propertyHolder.getPath(), propertyName )\n\t\t\t\t\t\t+ \"' is 'mappedBy' another entity and may not specify the '@JoinColumn'\" );\n\t\t\t}\n\t\t\tif ( propertyHolder.getJoinTable( property ) != null ) {\n\t\t\t\tthrow new AnnotationException( \"Association '\"\n\t\t\t\t\t\t+ qualify( propertyHolder.getPath(), propertyName )\n\t\t\t\t\t\t+ \"' is 'mappedBy' another entity and may not specify the '@JoinTable'\" );\n\t\t\t}\n\t\t\tif ( oneToMany ) {\n\t\t\t\tif ( property.hasDirectAnnotationUsage( MapKeyColumn.class ) ) {\n\t\t\t\t\tBOOT_LOGGER.mappedByShouldNotSpecifyMapKeyColumn(\n\t\t\t\t\t\t\tqualify( propertyHolder.getPath(), propertyName )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif ( property.hasDirectAnnotationUsage( OrderColumn.class ) ) {\n\t\t\t\t\tBOOT_LOGGER.mappedByShouldNotSpecifyOrderColumn(\n\t\t\t\t\t\t\tqualify( propertyHolder.getPath(), propertyName )\n\t\t\t\t\t);","sourceCodeStart":1173,"sourceCodeEnd":1209,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java#L1173-L1209","documentation":"The mappedBy side of an association is the unowned side: it mirrors the join defined by the owning side and cannot declare its own join mapping. detectMappedByProblem throws this AnnotationException when a mappedBy collection property also carries a direct @JoinColumn or @JoinColumns annotation.","triggerScenarios":"isMappedBy is true for the property and property.hasDirectAnnotationUsage(JoinColumn.class) or JoinColumns.class returns true during detectMappedByProblem; the parallel check for @JoinTable produces a sibling error.","commonSituations":"Specifying a FK column name on both sides of a bidirectional relation 'for symmetry'; migrating a unidirectional relation to bidirectional without removing the join column from what becomes the inverse side; generator output that always emits @JoinColumn.","solutions":["Remove @JoinColumn/@JoinColumns from the mappedBy side","Define the join column once on the owning side (the side without mappedBy)","If this side must own the join, remove mappedBy and give this side @JoinColumn(s) - then clean the other side to mappedBy"],"exampleFix":"// before\n@Entity\nclass Comment {\n    @ManyToOne\n    @JoinColumn(name = \"post_id\")\n    Post post;\n}\n\n@Entity\nclass Post {\n    @OneToMany(mappedBy = \"post\")\n    @JoinColumn(name = \"post_id\")   // error: mappedBy side may not declare join columns\n    List<Comment> comments;\n}\n\n// after\n@Entity\nclass Post {\n    @OneToMany(mappedBy = \"post\")   // join defined solely by Comment.post\n    List<Comment> comments;\n}","handlingStrategy":"validation","validationCode":"// Reject @JoinColumn on the mappedBy side before boot\nstatic void checkMappedByJoinColumns(Class<?>... entities) {\n    for ( Class<?> c : entities ) {\n        for ( Field f : c.getDeclaredFields() ) {\n            String mappedBy = null;\n            OneToMany otm = f.getAnnotation( OneToMany.class );\n            ManyToMany mtm = f.getAnnotation( ManyToMany.class );\n            if ( otm != null ) mappedBy = otm.mappedBy();\n            if ( mtm != null ) mappedBy = mtm.mappedBy();\n            boolean join = f.isAnnotationPresent( JoinColumn.class )\n                || f.isAnnotationPresent( JoinColumns.class );\n            if ( mappedBy != null && !mappedBy.isBlank() && join ) {\n                throw new IllegalStateException( \"mappedBy side declares @JoinColumn: \"\n                    + c.getName() + \".\" + f.getName() );\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Rule of thumb: a mappedBy side carries no join metadata of any kind (@JoinColumn, @JoinTable, @OrderBy-index columns)","Define the FK once on the owning side and let the inverse side mirror it via mappedBy","Add the mappedBy/@JoinColumn reflection scan to the mapping test suite"],"tags":["hibernate","jpa","mapped-by","join-column","bidirectional","annotation-binding"],"backgroundTag":"mappedby-joincolumn-conflict","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}