hibernate/hibernate-orm · error · UnsupportedOperationException

Composite key breakdown not yet implemented

Error message

Composite key breakdown not yet implemented

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/action/queue/spi/meta/TableDescriptorAsTableMapping.java:118

		@Override
		public void forEachKeyColumn(KeyColumnConsumer consumer) {
			for ( int i = 0; i < keyColumns.size(); i++ ) {
				consumer.consume( i, keyColumns.get( i ) );
			}
		}

		@Override
		public void breakDownKeyJdbcValues(
				Object domainValue,
				KeyValueConsumer valueConsumer,
				SharedSessionContractImplementor session) {
			// For simple keys, the domain value is the JDBC value
			// For composite keys, this would need more complex handling
			if ( keyColumns.size() == 1 ) {
				valueConsumer.consume( domainValue, keyColumns.get( 0 ) );
			}
			else {
				throw new UnsupportedOperationException( "Composite key breakdown not yet implemented" );
			}
		}

		@Override
		public <K> DomainResult<K> createDomainResult(
				NavigablePath navigablePath,
				TableReference tableReference,
				String resultVariable,
				DomainResultCreationState creationState) {
			throw new UnsupportedOperationException( "Domain result creation not needed for mutations" );
		}

		@Override
		public int getJdbcTypeCount() {
			return keyDescriptor.getJdbcTypeCount();
		}

		@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. Introduce a single-column surrogate key (@Id @GeneratedValue) and demote the composite columns to a unique constraint.
  2. Until supported, run the affected persistence context with hibernate.flush.queue.type=legacy.
  3. Report/upvote composite-key support for the new queue in Hibernate JIRA with your mapping as a reproducer.

Example fix

// before
@EmbeddedId
private OrderLineId id; // 2 columns -> UnsupportedOperationException
// after
@Id @GeneratedValue
private Long id;
@Embeddable
private OrderLineId naturalKey; // backed by a unique constraint
Defensive patterns

Strategy: validation

Validate before calling

// guard: composite keys are unsupported by the new queue's key breakdown
int keyCols = sessionFactory.getMappingMetamodel()
    .getEntityDescriptor(entityClass)
    .getIdentifierMapping()
    .getJdbcTypeCount();
if (keyCols > 1) {
    // use a surrogate key or hibernate.flush.queue.type=legacy
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/d90f65680d68d51e. Report an issue: GitHub.