{"record":{"id":"89a79a66e7e3756f","repo":"hibernate/hibernate-orm","slug":"many-to-any-mapping-s-needs-to-specify-2-or-89a79a","errorCode":null,"errorMessage":"<many-to-any /> mapping [%s] needs to specify 2 or more columns","messagePattern":"<many-to-any /> mapping \\[(.+?)\\] needs to specify 2 or more columns","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/PluralAttributeMapKeyManyToAnySourceImpl.java","lineNumber":82,"sourceCode":"\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String getSourceName() {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic List getColumnOrFormulaElements() {\n\t\t\t\t\t\treturn jaxbMapKeyManyToAnyMapping.getColumn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t);\n\n\t\t// the list of relational values should contain 2 or more values:\n\t\t//\t\t* the first represents the discriminator\n\t\t//\t\t* the rest represent the fk\n\n\t\tif ( relationalValueSources.size() < 2 ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\tLocale.ENGLISH,\n\t\t\t\t\t\t\t\"<many-to-any /> mapping [%s] needs to specify 2 or more columns\",\n\t\t\t\t\t\t\tpluralAttributeSource.getAttributeRole().getFullPath()\n\t\t\t\t\t),\n\t\t\t\t\tmappingDocument.getOrigin()\n\t\t\t);\n\t\t}\n\n\t\tthis.discriminatorSource = new AnyDiscriminatorSource() {\n\t\t\tprivate final HibernateTypeSource discriminatorTypeSource = new HibernateTypeSourceImpl( jaxbMapKeyManyToAnyMapping.getMetaType() );\n\t\t\tprivate final RelationalValueSource discriminatorRelationalValueSource = relationalValueSources.get( 0 );\n\n\t\t\t// the DTD/XSD currently do not allow discriminator mapping here\n\t\t\tprivate final Map<String,String> discriminatorValueMapping = Collections.emptyMap();\n//\t\tthis.discriminatorValueMapping = new HashMap<String, String>();\n//\t\tfor ( JaxbHbmAnyValueMappingType valueMapping : jaxbMapKeyManyToAnyMapping.getMetaValue() ) {\n//\t\t\tdiscriminatorValueMapping.put(","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/PluralAttributeMapKeyManyToAnySourceImpl.java#L64-L100","documentation":"<map-key-many-to-any/> maps a <map> whose key is a polymorphic reference. Such a key needs at least two relational values: the first column is the discriminator (resolved through meta-type) and the rest form the foreign key. PluralAttributeMapKeyManyToAnySourceImpl aborts bootstrap when fewer than two column/formula definitions are supplied for the key.","triggerScenarios":"A <map> mapping containing <map-key-many-to-any meta-type='string' id-type='long'> with zero or one <column> child, so the built relational value source list has size < 2.","commonSituations":"Polymorphic map keys are rare and usually come from old Hibernate 2/3-era mappings or interface-keyed domain models; converting a normal <map-key> to polymorphic without altering the table; assuming the fk column alone identifies the key entity.","solutions":["Declare two or more columns inside <map-key-many-to-any>: the first is the discriminator, the rest are the fk of the referenced entity","Verify meta-type/id-type and any <meta-value .../> mappings resolve the discriminator values to entity names","Consider remodelling: an embeddable or dedicated association table is often simpler than a polymorphic map key"],"exampleFix":"// before\n<map name='refs' table='refs'>\n    <map-key-many-to-any meta-type='string' id-type='long'>\n        <column name='ref_id'/>\n    </map-key-many-to-any>\n    ...\n</map>\n\n// after\n<map name='refs' table='refs'>\n    <map-key-many-to-any meta-type='string' id-type='long'>\n        <column name='ref_type'/>\n        <column name='ref_id'/>\n    </map-key-many-to-any>\n    ...\n</map>","handlingStrategy":"validation","validationCode":"// Pre-flight: every <map-key-many-to-any> must declare >= 2 columns\nvar key = (org.w3c.dom.Element) doc.getElementsByTagName(\"map-key-many-to-any\").item(0);\nint n = key.getElementsByTagName(\"column\").getLength();\nif (n < 2)\n    throw new IllegalStateException(\"map-key-many-to-any needs discriminator + fk columns, found \" + n);","typeGuard":null,"tryCatchPattern":"catch (org.hibernate.boot.MappingException e) at Metadata build: the message carries the map's attribute role - locate the <map-key-many-to-any> element and add the discriminator column first, then the fk column(s)","preventionTips":["Treat polymorphic map keys as an advanced feature - verify the key table has both a discriminator and fk columns","Review legacy Hibernate 2/3 mappings for <map-key-many-to-any> during upgrades","Consider an embeddable key or association table instead of a polymorphic map key"],"tags":["hibernate","hbm","map-key","many-to-any","mapping","orm"],"backgroundTag":"mapping-column-count-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}