{"record":{"id":"1d2a1ffbf2aeee93","repo":"hibernate/hibernate-orm","slug":"collection-id-mapping-has-wrong-number-of-columns","errorCode":null,"errorMessage":"collection id mapping has wrong number of columns: \" + getRole() + \" type: \" + getIdentifier().getType().getName()","messagePattern":"collection id mapping has wrong number of columns: \" \\+ getRole\\(\\) \\+ \" type: \" \\+ getIdentifier\\(\\)\\.getType\\(\\)\\.getName\\(\\)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java","lineNumber":79,"sourceCode":"\t\t\t&& isSame( identifier, other.identifier );\n\t}\n\n\tvoid createPrimaryKey() {\n\t\tif ( !isOneToMany() ) {\n\t\t\tfinal var primaryKey = new PrimaryKey( getCollectionTable() );\n\t\t\tprimaryKey.addColumns( getIdentifier() );\n\t\t\tgetCollectionTable().setPrimaryKey( primaryKey );\n\t\t}\n\t\t// create an index on the key columns??\n\t}\n\n\tpublic void validate(MappingContext mappingContext) throws MappingException {\n\t\tsuper.validate( mappingContext );\n\n\t\tassert getElement() != null : \"IdentifierCollection identifier not bound : \" + getRole();\n\n\t\tif ( !getIdentifier().isValid( mappingContext ) ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\"collection id mapping has wrong number of columns: \" +\n\t\t\t\tgetRole() +\n\t\t\t\t\" type: \" +\n\t\t\t\tgetIdentifier().getType().getName()\n\t\t\t);\n\t\t}\n\t}\n}\n","sourceCodeStart":61,"sourceCodeEnd":88,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java#L61-L88","documentation":"IdentifierCollection#validate checks the surrogate id mapping of an idbag collection (<idbag> / @CollectionId) and throws when the id Value is not valid - in practice its column span does not match the declared type, for example a multi-column type used as the collection id.","triggerScenarios":"A @CollectionId whose type maps to more than one column; an hbm <collection-id> whose type/column combination does not resolve; forgetting the @Column for the collection id; using an array or composite type as the bag id.","commonSituations":"Legacy idbag mappings migrated between Hibernate versions; introducing custom types into @CollectionId; hand-editing hbm <idbag> elements.","solutions":["Give the collection id a single-column basic type (long, or UUID stored as one column) with an explicit @Column.","Declare the generator explicitly on @CollectionId (e.g. a sequence generator) so the id resolves cleanly.","Where possible replace legacy idbags with a normal @ElementCollection plus @OrderColumn, or promote the bag to an owning entity row."],"exampleFix":"// before - multi-column type as collection id\n@CollectionId(\n    columns = @Column(name = \"bag_id\"),\n    type = @Type(StringArrayType.class),\n    generator = \"seq\"\n)\nCollection<String> tags;\n\n// after - single-column basic type\n@CollectionId(\n    columns = @Column(name = \"bag_id\"),\n    type = @Type(LongType.class),\n    generator = \"seq\"\n)\nCollection<String> tags;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    metadata = sources.buildMetadata();\n} catch (MappingException e) {\n    // message contains the collection role + id type name - inspect the\n    // @CollectionId / <collection-id> of that role\n    throw e;\n}","preventionTips":["Prefer @ElementCollection with @OrderColumn over legacy @CollectionId/idbag for new mappings.","Always specify columns, type, and generator explicitly on @CollectionId.","Cover every collection mapping with a Metadata-building unit test."],"tags":["hibernate","orm","mapping","idbag","collection-id","element-collection"],"backgroundTag":"collection-id-mapping-error","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}