{"record":{"id":"0bf9a65091a8ecee","repo":"hibernate/hibernate-orm","slug":"many-to-any-mapping-s-needs-to-specify-2-or","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/PluralAttributeElementSourceManyToAnyImpl.java","lineNumber":67,"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 jaxbManyToAnyMapping.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( jaxbManyToAnyMapping.getMetaType() );\n\t\t\tprivate final RelationalValueSource discriminatorRelationalValueSource = relationalValueSources.get( 0 );\n\t\t\tprivate final Map<String,String> discriminatorValueMapping = new HashMap<>();\n\t\t\t{\n\t\t\t\tfor ( JaxbHbmAnyValueMappingType valueMapping : jaxbManyToAnyMapping.getMetaValue() ) {\n\t\t\t\t\tdiscriminatorValueMapping.put(\n\t\t\t\t\t\t\tvalueMapping.getValue(),\n\t\t\t\t\t\t\tmappingDocument.qualifyClassName( valueMapping.getClazz() )","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/PluralAttributeElementSourceManyToAnyImpl.java#L49-L85","documentation":"<many-to-any/> maps a collection whose elements are polymorphic references chosen by a discriminator. The mapping needs at least two relational values: the first column holds the discriminator value (resolved through meta-type to an entity name) and the remaining column(s) form the foreign key of the referenced entity. If fewer than two column/formula definitions are supplied, the plural-attribute element source rejects the mapping at bootstrap.","triggerScenarios":"A <many-to-any meta-type='string' id-type='long'> element inside a collection mapping (<bag>, <set>, <list>, <idbag>, <array> element position) that declares zero or one <column> child, so relationalValueSources.size() < 2 in PluralAttributeElementSourceManyToAnyImpl.","commonSituations":"Authors used to <many-to-many> or <element> assume one fk column suffices; converting an existing collection to polymorphic without adding a discriminator column to the join table; the table DDL genuinely has only a single fk column and cannot support <many-to-any>.","solutions":["Add the missing columns: first <column> is the discriminator (its values must map through meta-type to entity names), the remaining <column> elements are the foreign key","Check meta-type and id-type match what the columns actually store, and add <meta-value .../> entries where discriminator values differ from entity names","If the table truly has only one column, <many-to-any> cannot work there - use a plain association or restructure the table first"],"exampleFix":"// before\n<many-to-any name='items' meta-type='string' id-type='long'>\n    <column name='item_id'/>\n</many-to-any>\n\n// after - discriminator column added as first column\n<many-to-any name='items' meta-type='string' id-type='long'>\n    <column name='item_type'/>\n    <column name='item_id'/>\n</many-to-any>","handlingStrategy":"validation","validationCode":"// Pre-flight: every <many-to-any> must declare >= 2 columns\nvar m2a = (org.w3c.dom.Element) doc.getElementsByTagName(\"many-to-any\").item(0);\nint n = m2a.getElementsByTagName(\"column\").getLength();\nif (n < 2)\n    throw new IllegalStateException(\"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 full attribute role (e.g. Entity.items) - use it to jump straight to the collection element in hbm.xml and add the missing discriminator/fk columns","preventionTips":["Design the join table with discriminator + fk columns before writing <many-to-any>","Remember the ordering rule: column #1 is the discriminator, the rest are the fk","Prefer the annotation form (@Any/@ManyToAny with explicit column defs) where the two-column requirement is more visible"],"tags":["hibernate","hbm","many-to-any","polymorphism","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"}