hibernate/hibernate-orm · error · UnsupportedOperationException

Unsupported foreign key part:

Error message

Unsupported foreign key part: 

What it means

Thrown while StructJdbcType unpacks raw JDBC values of a struct-typed aggregate column. When the embeddable mapped into the struct contains a to-one association, Hibernate reads the association's ForeignKeyDescriptor key part; only basic-valued (single-column FK) and embeddable-valued (composite FK) key parts are implemented. Any other key-part shape raises this explicit UnsupportedOperationException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java:395

			WrapperOptions options) throws SQLException {
		final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
		for ( int i = 0; i < numberOfAttributeMappings + ( embeddableMappingType.isPolymorphic() ? 1 : 0 ); i++ ) {
			final ValuedModelPart attributeMapping = getSubPart( embeddableMappingType, i );
			if ( attributeMapping instanceof ToOneAttributeMapping toOneAttributeMapping ) {
				if ( toOneAttributeMapping.getSideNature() == ForeignKeyDescriptor.Nature.TARGET ) {
					continue;
				}
				final ValuedModelPart keyPart = toOneAttributeMapping.getForeignKeyDescriptor().getKeyPart();
				if ( keyPart instanceof BasicValuedMapping ) {
					wrapRawJdbcValue( keyPart.getSingleJdbcMapping(), jdbcValues, jdbcIndex, options );
					jdbcIndex++;
				}
				else if ( keyPart instanceof EmbeddableValuedModelPart embeddableValuedModelPart ) {
					final EmbeddableMappingType mappingType = embeddableValuedModelPart.getEmbeddableTypeDescriptor();
					jdbcIndex = wrapRawJdbcValues( mappingType, jdbcValues, jdbcIndex, options );
				}
				else {
					throw new UnsupportedOperationException( "Unsupported foreign key part: " + keyPart );
				}
			}
			else if ( attributeMapping instanceof PluralAttributeMapping ) {
				continue;
			}
			else if ( attributeMapping instanceof DiscriminatedAssociationAttributeMapping discriminatedMapping ) {
				wrapRawJdbcValue(
						discriminatedMapping.getDiscriminatorMapping()
								.getSingleJdbcMapping(),
						jdbcValues,
						jdbcIndex,
						options
				);
				jdbcIndex++;
				wrapRawJdbcValue(
						discriminatedMapping.getKeyPart().getSingleJdbcMapping(),
						jdbcValues,
						jdbcIndex,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Map the association's FK columns as plain basic attributes inside the embeddable instead of a @ManyToOne/@OneToOne.
  2. Move the association out of the struct-mapped embeddable onto the owning entity.
  3. Select the struct's component columns in the native query instead of the whole struct value.
  4. Upgrade Hibernate to a version supporting this key-part kind, or file an issue with a mapping that reproduces it.

Example fix

// before
@Embeddable
public class Address {
    String street;
    @ManyToOne            // to-one inside a struct aggregate
    Country country;      // -> Unsupported foreign key part
}
// after
@Embeddable
public class Address {
    String street;
    @Column(name = "country_code")
    String countryCode;   // plain basic FK column instead
}
Defensive patterns

Strategy: validation

Validate before calling

static void assertStructAggregateSafe(Class<?> embeddable) {
    for (Field f : embeddable.getDeclaredFields()) {
        if (f.isAnnotationPresent(ManyToOne.class) || f.isAnnotationPresent(OneToOne.class)
                || f.isAnnotationPresent(Any.class)) {
            throw new IllegalStateException(
                "Struct aggregate must not contain association: " + f
                + " (Unsupported foreign key part)");
        }
    }
}

Try / catch

try {
    return session.createNativeQuery("select address from users where id = :id", Address.class)
                  .setParameter("id", id).getSingleResult();
} catch (UnsupportedOperationException ex) {
    if (ex.getMessage() != null && ex.getMessage().startsWith("Unsupported foreign key part")) {
        throw new DataMappingException("Aggregate contains an unsupported association", ex);
    }
    throw ex;
}

Prevention

When it happens

Trigger: Reading a struct aggregate via StructJdbcType.extractJdbcValues (e.g. a native query selecting the struct column, or result mapping of an aggregate) where the embeddable has a @ManyToOne/@OneToone whose foreign-key key part is neither a BasicValuedMapping nor an EmbeddableValuedModelPart, e.g. derived-identity shapes (@ManyToOne @Id, @MapsId) where the key part is itself entity-valued.

Common situations: Modeling associations inside @Struct embeddables on Oracle OBJECT, PostgreSQL composite, or DB2 row types; upgrading Hibernate versions that introduced new FK part kinds; native queries returning the struct column directly instead of its components.

Related errors


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