{"record":{"id":"d90f65680d68d51e","repo":"hibernate/hibernate-orm","slug":"composite-key-breakdown-not-yet-implemented","errorCode":null,"errorMessage":"Composite key breakdown not yet implemented","messagePattern":"Composite key breakdown not yet implemented","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/action/queue/spi/meta/TableDescriptorAsTableMapping.java","lineNumber":118,"sourceCode":"\t\t@Override\n\t\tpublic void forEachKeyColumn(KeyColumnConsumer consumer) {\n\t\t\tfor ( int i = 0; i < keyColumns.size(); i++ ) {\n\t\t\t\tconsumer.consume( i, keyColumns.get( i ) );\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void breakDownKeyJdbcValues(\n\t\t\t\tObject domainValue,\n\t\t\t\tKeyValueConsumer valueConsumer,\n\t\t\t\tSharedSessionContractImplementor session) {\n\t\t\t// For simple keys, the domain value is the JDBC value\n\t\t\t// For composite keys, this would need more complex handling\n\t\t\tif ( keyColumns.size() == 1 ) {\n\t\t\t\tvalueConsumer.consume( domainValue, keyColumns.get( 0 ) );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new UnsupportedOperationException( \"Composite key breakdown not yet implemented\" );\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic <K> DomainResult<K> createDomainResult(\n\t\t\t\tNavigablePath navigablePath,\n\t\t\t\tTableReference tableReference,\n\t\t\t\tString resultVariable,\n\t\t\t\tDomainResultCreationState creationState) {\n\t\t\tthrow new UnsupportedOperationException( \"Domain result creation not needed for mutations\" );\n\t\t}\n\n\t\t@Override\n\t\tpublic int getJdbcTypeCount() {\n\t\t\treturn keyDescriptor.getJdbcTypeCount();\n\t\t}\n\n\t\t@Override","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/action/queue/spi/meta/TableDescriptorAsTableMapping.java#L100-L136","documentation":"TableDescriptorAsTableMapping.breakDownKeyJdbcValues decomposes a key domain value into per-column JDBC values, but the adapter only implements the single-column case (keyColumns.size() == 1). A key spanning two or more columns - an @EmbeddedId/@IdClass composite key - throws UnsupportedOperationException instead of producing wrong SQL. It is an explicit 'not yet implemented' gap in the new action-queue meta layer, not a configuration error.","triggerScenarios":"Flushing or mutating an entity (or table) whose key mapping resolves to 2+ key columns through code that calls breakDownKeyJdbcValues on this adapter - e.g. composite-key entities under the new graph-based flush machinery.","commonSituations":"Legacy schemas with natural composite primary keys; early adoption of Hibernate 8's incubating graph-based action queue whose mutation meta layer has not grown composite-key support yet.","solutions":["Introduce a single-column surrogate key (@Id @GeneratedValue) and demote the composite columns to a unique constraint.","Until supported, run the affected persistence context with hibernate.flush.queue.type=legacy.","Report/upvote composite-key support for the new queue in Hibernate JIRA with your mapping as a reproducer."],"exampleFix":"// before\n@EmbeddedId\nprivate OrderLineId id; // 2 columns -> UnsupportedOperationException\n// after\n@Id @GeneratedValue\nprivate Long id;\n@Embeddable\nprivate OrderLineId naturalKey; // backed by a unique constraint","handlingStrategy":"validation","validationCode":"// guard: composite keys are unsupported by the new queue's key breakdown\nint keyCols = sessionFactory.getMappingMetamodel()\n    .getEntityDescriptor(entityClass)\n    .getIdentifierMapping()\n    .getJdbcTypeCount();\nif (keyCols > 1) {\n    // use a surrogate key or hibernate.flush.queue.type=legacy\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer single-column surrogate primary keys over natural composite keys","Run an integration test that flushes every entity type before enabling the graph queue","Watch Hibernate release notes for composite-key support in the new action queue"],"tags":["hibernate","composite-key","unsupported-feature","action-queue","flush"],"backgroundTag":"composite-key-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}