hibernate/hibernate-orm · error · UnsupportedOperationException

Unsupported foreign key part:

Error message

Unsupported foreign key part: 

What it means

StructHelper.injectJdbcValue() decomposes aggregate-mapped (json/struct) embeddables into plain JDBC values for foreign-key handling. For a ToOneAttributeMapping it accepts only FK key parts that are BasicValuedMapping (single-column FK) or EmbeddableValuedModelPart (composite FK); any other key part throws UnsupportedOperationException('Unsupported foreign key part: <part>'). The mapped association's foreign key has a shape Hibernate cannot decompose in this path.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructHelper.java:247

					attributeValues[attributeIndex],
					ForeignKeyDescriptor.Nature.TARGET,
					options.getSession()
			);
			if ( keyPart instanceof BasicValuedMapping ) {
				jdbcValueCount = 1;
				jdbcValues[jdbcIndex] = foreignKeyValue;
			}
			else if ( keyPart instanceof EmbeddableValuedModelPart embeddableValuedModelPart ) {
				jdbcValueCount = injectJdbcValues(
						embeddableValuedModelPart.getEmbeddableTypeDescriptor(),
						foreignKeyValue,
						jdbcValues,
						jdbcIndex,
						options
				);
			}
			else {
				throw new UnsupportedOperationException( "Unsupported foreign key part: " + keyPart );
			}
		}
		else if ( attributeMapping instanceof PluralAttributeMapping ) {
			return 0;
		}
		else if ( attributeMapping instanceof DiscriminatedAssociationAttributeMapping ) {
			jdbcValueCount = attributeMapping.decompose(
					attributeValues[attributeIndex],
					jdbcIndex,
					jdbcValues,
					options,
					(valueIndex, objects, wrapperOptions, value, jdbcValueMapping)
							-> objects[valueIndex] = value,
					options.getSession()
			);
		}
		else if ( attributeMapping instanceof EmbeddableValuedModelPart embeddableValuedModelPart ) {
			final EmbeddableMappingType embeddableMappingType = embeddableValuedModelPart.getMappedType();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove associations from the aggregate-mapped embeddable: represent the FK as a plain basic column (an id attribute with @Column) and map the @ManyToOne on the owning entity outside the aggregate.
  2. Split the embeddable so aggregate-mapped ones contain only basic and nested-embeddable parts.
  3. Check for a newer Hibernate release - support for association shapes in aggregate FK decomposition has changed across 6.x versions.

Example fix

// before: association inside the aggregate-mapped embeddable
@Embeddable public class OrderInfo {
    String note;
    @ManyToOne Customer customer; // FK key part is an aggregate -> unsupported
}

// after: keep the aggregate plain; move the association to the entity
@Embeddable public class OrderInfo {
    String note;
    Long customerId; // basic FK column
}
@Entity public class Order {
    @Embedded OrderInfo info;
    @ManyToOne @JoinColumn(name = "customer_id") Customer customer;
}
Defensive patterns

Strategy: validation

Validate before calling

// At startup, assert aggregate embeddables contain only basic or embeddable parts
static void assertAggregateEmbeddableIsPlain(Class<?> embeddable) {
    for (java.lang.reflect.Field f : embeddable.getDeclaredFields()) {
        if (f.isAnnotationPresent(jakarta.persistence.ManyToOne.class)
                || f.isAnnotationPresent(jakarta.persistence.OneToOne.class)) {
            throw new IllegalStateException(
                embeddable.getName() + '.' + f.getName()
                + " is an association inside an aggregate-mapped embeddable - move it to the owning entity");
        }
    }
}

Try / catch

try {
    session.flush();
} catch (UnsupportedOperationException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unsupported foreign key part")) {
        // message names the FK key part Hibernate cannot decompose:
        // replace the embedded association with a basic FK column on the owning entity
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: An aggregate (STRUCT/JSON) mapping whose embeddable contains a @ManyToOne/@OneToMany-side association whose foreign-key key part is neither basic nor embeddable valued - e.g., an association keyed by an aggregate/json id or another exotic part - hit during flush/decompose of the mapping.

Common situations: Embeddables shared between plain relational mappings and struct/json aggregate mappings that contain associations; porting Oracle/Postgres struct mappings; entity ids modeled as json aggregates; Hibernate version changes that made this helper path reachable for previously working mappings.

Related errors


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