{"record":{"id":"181b52e0bdf61262","repo":"hibernate/hibernate-orm","slug":"attribute-types-for-a-dynamicentity-must-be-explic","errorCode":null,"errorMessage":"Attribute types for a dynamicEntity must be explicitly specified: \" + propertyName","messagePattern":"Attribute types for a dynamicEntity must be explicitly specified: \" \\+ propertyName","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java","lineNumber":643,"sourceCode":"\t\tthis.attributeConverterDescriptor = descriptor;\n\t}\n\n\tprotected ConverterDescriptor<?,?> getAttributeConverterDescriptor() {\n\t\treturn attributeConverterDescriptor;\n\t}\n\n\t@Override\n\tpublic void setTypeUsingReflection(String className, String propertyName) throws MappingException {\n\t\t// NOTE: this is called as the last piece in setting SimpleValue type information,\n\t\t//       and implementations rely on that fact, using it as a signal that all\n\t\t//       the information it is going to get is already specified at this point\n\t\tif ( typeName == null && type == null ) {\n\t\t\tif ( attributeConverterDescriptor == null ) {\n\t\t\t\t// This is here to work like legacy. This should change when we integrate with metamodel\n\t\t\t\t// to look for JdbcType and JavaType individually and create the BasicType (well, really\n\t\t\t\t// keep a registry of [JdbcType,JavaType] -> BasicType...)\n\t\t\t\tif ( className == null ) {\n\t\t\t\t\tthrow new MappingException(\n\t\t\t\t\t\t\t\"Attribute types for a dynamic entity must be explicitly specified: \" + propertyName );\n\t\t\t\t}\n\t\t\t\ttypeName = getClass( className, propertyName ).getName();\n\t\t\t\t// TODO: To fully support isNationalized here we need to do the process hinted at above\n\t\t\t\t// \t\t essentially, much of the logic from #buildAttributeConverterTypeAdapter wrt\n\t\t\t\t// \t\t resolving a (1) JdbcType, a (2) JavaType and dynamically building a BasicType\n\t\t\t\t// \t\t combining them.\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// we had an AttributeConverter\n\t\t\t\ttype = buildAttributeConverterTypeAdapter();\n\t\t\t}\n\t\t}\n\t\t// otherwise assume either\n\t\t// (a) explicit type was specified or\n\t\t// (b) determine was already performed\n\t}\n","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java#L625-L661","documentation":"Thrown by SimpleValue.setTypeUsingReflection when Hibernate must determine a property type by reflecting on a class, but className is null — which is always the case for dynamic-map (entity-name based) entities, since they have no Java class to reflect on. Dynamic entities exist only as Maps of names to values, so every property must declare its type explicitly in the mapping. Without a type attribute there is no way for Hibernate to know what to store in the map slot.","triggerScenarios":"Using hbm.xml <hibernate-mapping> with entity-name=\"...\" (dynamic-map representation) and a <property name=\"x\"/> element that omits the type attribute and has no @Type/@TypeDef equivalent; also a @ManyToOne in a dynamic entity without class/target entity; similarly for <key-property> and other value mappings in dynamic-map mode when no type name was supplied.","commonSituations":"Legacy Hibernate 2/3-style dynamic-map mappings where a type attribute was accidentally dropped; migrating mappings to dynamic entities and forgetting that reflection cannot backfill types; XML edited by hand or generated by tools that omit type=\"...\"; using SessionFactory.openStatelessSession with entity-name APIs against incompletely typed mappings.","solutions":["Add an explicit type attribute to every untyped property of the dynamic entity, e.g. <property name=\"amount\" type=\"big_decimal\"/> or type=\"org.example.MyType\".","For association properties, supply the entity class: <many-to-one name=\"customer\" class=\"Customer\"/>.","If reflection-based type discovery is desired, map the entity as a normal POJO class instead of entity-name/dynamic-map.","Run Metadata building early (e.g. a startup test that builds SessionFactory) so this surfaces at deploy time, not first use."],"exampleFix":"<!-- before -->\n<hibernate-mapping>\n  <class entity-name=\"Item\">\n    <id name=\"id\" type=\"long\"/>\n    <property name=\"price\"/>  <!-- missing type -->\n  </class>\n</hibernate-mapping>\n\n<!-- after -->\n<hibernate-mapping>\n  <class entity-name=\"Item\">\n    <id name=\"id\" type=\"long\"/>\n    <property name=\"price\" type=\"big_decimal\"/>\n  </class>\n</hibernate-mapping>","handlingStrategy":"validation","validationCode":"// fail fast when bootstrapping dynamic-map mappings: verify every property has a type\nMetadata metadata = metadataSources.buildMetadata(); // throws MappingException with the property name if a type is missing","typeGuard":null,"tryCatchPattern":"try {\n    sessionFactory = cfg.buildSessionFactory();\n} catch (MappingException e) {\n    if (e.getMessage().startsWith(\"Attribute types for a dynamic entity\")) {\n        // message contains the offending property name — log and surface config guidance\n        log.error(\"Dynamic-entity property missing 'type' attribute: {}\", e.getMessage());\n    }\n    throw e;\n}","preventionTips":["In dynamic-map hbm.xml, always write an explicit type= attribute on <property>/<id>/<many-to-one>.","Consider a startup validator that parses hbm files and flags <property> elements without type attributes.","Prefer POJO entities when type-by-reflection is desired."],"tags":["hibernate","dynamic-map","hbm-xml","type-resolution","orm-mapping"],"backgroundTag":"missing-type-mapping","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}