{"record":{"id":"a9bc9d153a48b072","repo":"hibernate/hibernate-orm","slug":"only-classes-not-interfaces-may-be-mapped-as-en","errorCode":null,"errorMessage":"Only classes (not interfaces) may be mapped as @Entity : \" + classDetails.getName()","messagePattern":"Only classes \\(not interfaces\\) may be mapped as @Entity : \" \\+ classDetails\\.getName\\(\\)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/ManagedTypeProcessor.java","lineNumber":140,"sourceCode":"\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t);\n\n\t\t\tDynamicModelHelper.prepareDynamicClass( classDetails, jaxbEntity, xmlDocumentContext );\n\t\t}\n\t\telse {\n\t\t\tmemberAdjuster = ManagedTypeProcessor::adjustCompleteNonDynamicTypeMember;\n\t\t\tfinal String className = XmlProcessingHelper.determineClassName( jaxbRoot, jaxbEntity );\n\t\t\tclassDetails = (MutableClassDetails) classDetailsRegistry.resolveClassDetails( className );\n\t\t\tclassAccessType = coalesce(\n\t\t\t\t\tjaxbEntity.getAccess(),\n\t\t\t\t\tjaxbRoot.getAccess(),\n\t\t\t\t\txmlDocumentContext.getEffectiveDefaults().getDefaultPropertyAccessType(),\n\t\t\t\t\tdefaultAccessTypeFromDefaultAccessor( xmlDocumentContext ),\n\t\t\t\t\tAccessType.PROPERTY\n\t\t\t);\n\t\t\tif ( classDetails.isInterface() ) {\n\t\t\t\tthrow new MappingException( \"Only classes (not interfaces) may be mapped as @Entity : \" + classDetails.getName() );\n\t\t\t}\n\n\t\t\tclassDetails.forEachPersistableMember( memberDetails -> {\n\t\t\t\tfinal var mutableMemberDetails = (MutableMemberDetails) memberDetails;\n\t\t\t\tmutableMemberDetails.clearAnnotationUsages();\n\t\t\t} );\n\t\t}\n\n\t\tclassDetails.clearAnnotationUsages();\n\n\t\t// In metadata-complete mode the XML is the sole source of truth — annotations have just\n\t\t// been cleared, so the chosen access type must be stamped on the class regardless of\n\t\t// whether it came from XML or from a fallback.\n\t\tapplyAccessAnnotation( classAccessType, classDetails, xmlDocumentContext );\n\n\t\t// from here, processing is the same between override and metadata-complete modes\n\t\t// (aside from the dynamic model handling)\n","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/ManagedTypeProcessor.java#L122-L158","documentation":"Error \"Only classes (not interfaces) may be mapped as @Entity : \" + classDetails.getName()\" thrown in hibernate/hibernate-orm.","triggerScenarios":"An hbm.xml / orm.xml mapping document violates a mapping rule during bootstrap.","commonSituations":"Legacy XML mappings with invalid combinations (column+formula, mixed inheritance, missing identifiers, bad extends references).","solutions":["Remove @Entity from the interface; map a concrete class instead, or use the interface only as a target of associations via targetEntity."],"exampleFix":"Remove @Entity from the interface; map a concrete class instead, or use the interface only as a target of associations via targetEntity.","handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}