{"record":{"id":"de3a4c33b7db7b3f","repo":"hibernate/hibernate-orm","slug":"unsupported-foreign-key-part-de3a4c","errorCode":null,"errorMessage":"Unsupported foreign key part: ","messagePattern":"Unsupported foreign key part: ","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java","lineNumber":395,"sourceCode":"\t\t\tWrapperOptions options) throws SQLException {\n\t\tfinal int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();\n\t\tfor ( int i = 0; i < numberOfAttributeMappings + ( embeddableMappingType.isPolymorphic() ? 1 : 0 ); i++ ) {\n\t\t\tfinal ValuedModelPart attributeMapping = getSubPart( embeddableMappingType, i );\n\t\t\tif ( attributeMapping instanceof ToOneAttributeMapping toOneAttributeMapping ) {\n\t\t\t\tif ( toOneAttributeMapping.getSideNature() == ForeignKeyDescriptor.Nature.TARGET ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfinal ValuedModelPart keyPart = toOneAttributeMapping.getForeignKeyDescriptor().getKeyPart();\n\t\t\t\tif ( keyPart instanceof BasicValuedMapping ) {\n\t\t\t\t\twrapRawJdbcValue( keyPart.getSingleJdbcMapping(), jdbcValues, jdbcIndex, options );\n\t\t\t\t\tjdbcIndex++;\n\t\t\t\t}\n\t\t\t\telse if ( keyPart instanceof EmbeddableValuedModelPart embeddableValuedModelPart ) {\n\t\t\t\t\tfinal EmbeddableMappingType mappingType = embeddableValuedModelPart.getEmbeddableTypeDescriptor();\n\t\t\t\t\tjdbcIndex = wrapRawJdbcValues( mappingType, jdbcValues, jdbcIndex, options );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new UnsupportedOperationException( \"Unsupported foreign key part: \" + keyPart );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( attributeMapping instanceof PluralAttributeMapping ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse if ( attributeMapping instanceof DiscriminatedAssociationAttributeMapping discriminatedMapping ) {\n\t\t\t\twrapRawJdbcValue(\n\t\t\t\t\t\tdiscriminatedMapping.getDiscriminatorMapping()\n\t\t\t\t\t\t\t\t.getSingleJdbcMapping(),\n\t\t\t\t\t\tjdbcValues,\n\t\t\t\t\t\tjdbcIndex,\n\t\t\t\t\t\toptions\n\t\t\t\t);\n\t\t\t\tjdbcIndex++;\n\t\t\t\twrapRawJdbcValue(\n\t\t\t\t\t\tdiscriminatedMapping.getKeyPart().getSingleJdbcMapping(),\n\t\t\t\t\t\tjdbcValues,\n\t\t\t\t\t\tjdbcIndex,","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/StructJdbcType.java#L377-L413","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Map the association's FK columns as plain basic attributes inside the embeddable instead of a @ManyToOne/@OneToOne.","Move the association out of the struct-mapped embeddable onto the owning entity.","Select the struct's component columns in the native query instead of the whole struct value.","Upgrade Hibernate to a version supporting this key-part kind, or file an issue with a mapping that reproduces it."],"exampleFix":"// before\n@Embeddable\npublic class Address {\n    String street;\n    @ManyToOne            // to-one inside a struct aggregate\n    Country country;      // -> Unsupported foreign key part\n}\n// after\n@Embeddable\npublic class Address {\n    String street;\n    @Column(name = \"country_code\")\n    String countryCode;   // plain basic FK column instead\n}","handlingStrategy":"validation","validationCode":"static void assertStructAggregateSafe(Class<?> embeddable) {\n    for (Field f : embeddable.getDeclaredFields()) {\n        if (f.isAnnotationPresent(ManyToOne.class) || f.isAnnotationPresent(OneToOne.class)\n                || f.isAnnotationPresent(Any.class)) {\n            throw new IllegalStateException(\n                \"Struct aggregate must not contain association: \" + f\n                + \" (Unsupported foreign key part)\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return session.createNativeQuery(\"select address from users where id = :id\", Address.class)\n                  .setParameter(\"id\", id).getSingleResult();\n} catch (UnsupportedOperationException ex) {\n    if (ex.getMessage() != null && ex.getMessage().startsWith(\"Unsupported foreign key part\")) {\n        throw new DataMappingException(\"Aggregate contains an unsupported association\", ex);\n    }\n    throw ex;\n}","preventionTips":["Keep struct and XML aggregates limited to basic attributes and nested embeddables.","Cover struct reads with an integration test that selects the aggregate column before release.","Review aggregate mappings after every Hibernate upgrade; FK part support changes between versions."],"tags":["hibernate","struct","aggregate-mapping","foreign-key","to-one"],"backgroundTag":"unsupported-mapping-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}