{"record":{"id":"9535ded5f2025540","repo":"hibernate/hibernate-orm","slug":"property-propertyname-may-not-be-annotated-b","errorCode":null,"errorMessage":"Property '<propertyName>' may not be annotated '@BatchSize'","messagePattern":"Property '<propertyName>' may not be annotated '@BatchSize'","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/binder/internal/BatchSizeBinder.java","lineNumber":44,"sourceCode":"\t@Override\n\tpublic void bind(BatchSize batchSize, MetadataBuildingContext context, PersistentClass persistentClass) {\n\t\tpersistentClass.setBatchSize( batchSize.size() );\n\t}\n\n\t@Override\n\tpublic void bind(BatchSize batchSize, MetadataBuildingContext context, Component embeddableClass) {\n\t\tthrow new AnnotationException(\"Class '\" + embeddableClass.getComponentClassName()\n\t\t\t\t+ \"' is an '@Embeddable' type and may not be annotated '@BatchSize'\");\n\t}\n\n\t@Override\n\tpublic void bind(BatchSize batchSize, MetadataBuildingContext context, PersistentClass persistentClass, Property property) {\n\t\tfinal Value value = property.getValue();\n\t\tif ( value instanceof Collection collection ) {\n\t\t\tcollection.setBatchSize( batchSize.size() );\n\t\t}\n\t\telse {\n\t\t\tthrow new AnnotationException(\"Property '\" + property.getName() + \"' may not be annotated '@BatchSize'\");\n\t\t}\n\t}\n}\n","sourceCodeStart":26,"sourceCodeEnd":48,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/binder/internal/BatchSizeBinder.java#L26-L48","documentation":"When @BatchSize sits on a property, BatchSizeBinder accepts only Collection values (lazy collection batch fetching). For any other property shape — @Basic, @ManyToOne, @OneToOne, @Embedded — the value is not a Collection and binding throws an AnnotationException naming the property. To-one batch fetching is configured on the target entity class, not the attribute.","triggerScenarios":"Annotating a non-collection attribute with @BatchSize, most commonly @ManyToOne(fetch = LAZY) or @OneToOne; at SessionFactory build the attribute binder sees a non-Collection Value and throws.","commonSituations":"Trying to enable batch fetching for lazy to-one associations by annotating the attribute (the annotation belongs on the referenced entity class); confusing entity-level with collection-level @BatchSize; stale annotation after changing an association's cardinality.","solutions":["For lazy @ManyToOne/@OneToOne batch fetching, move @BatchSize to the referenced @Entity class.","For @OneToMany/@ManyToMany/@ElementCollection, keep @BatchSize on the collection property — that is the supported case.","Otherwise delete the @BatchSize annotation from the property."],"exampleFix":"// before\n@Entity\npublic class Order {\n    @BatchSize(size = 20)\n    @ManyToOne(fetch = FetchType.LAZY)\n    private User user;\n}\n\n// after\n@Entity\n@BatchSize(size = 20) // applies when loading Users\npublic class User { ... }\n\n@Entity\npublic class Order {\n    @ManyToOne(fetch = FetchType.LAZY)\n    private User user;\n}","handlingStrategy":"validation","validationCode":"for (Field f : cls.getDeclaredFields()) {\n    if (f.isAnnotationPresent(org.hibernate.annotations.BatchSize.class)\n            && !java.util.Collection.class.isAssignableFrom(f.getType())) {\n        throw new IllegalStateException(\"@BatchSize only allowed on collection properties: \"\n                + cls.getName() + \".\" + f.getName());\n    }\n}","typeGuard":null,"tryCatchPattern":"Catch org.hibernate.AnnotationException around SessionFactory build; the message names the property. Fail fast — this is a mapping defect, not a runtime condition to recover from.","preventionTips":["Entity-level @BatchSize for to-one batch fetching; property-level only on collections.","Review annotations whenever an association's cardinality changes.","Add a reflection-based annotation lint to the test suite."],"tags":["hibernate","jpa","annotations","batch-size","lazy-loading","orm-mapping"],"backgroundTag":"jpa-annotation-misplacement","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}