hibernate/hibernate-orm · error · MappingException
Couldn't find column [${structColumnName}] that was defined
Error message
Couldn't find column [${structColumnName}] that was defined in @Struct(attributes) in the component [${componentClassName}] What it means
@Struct(attributes = {...}) lists the ordered attribute (column) names of the database struct type. AggregateComponentSecondPass reorders the mapped columns to match that list; when a listed name matches no column of the component mapping (addColumns returns false), Hibernate throws this MappingException naming the offending struct column and the component class.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java:290
addColumns( orderedColumns, component.getDiscriminator() );
}
}
else {
final List<Property> properties = component.getProperties();
for ( final int propertyIndex : propertyMappingIndex ) {
addColumns( orderedColumns, properties.get( propertyIndex ).getValue() );
}
}
final List<Column> reorderedColumn =
context.getBuildingOptions().getColumnOrderingStrategy()
.orderUserDefinedTypeColumns( userDefinedType, context.getMetadataCollector() );
userDefinedType.reorderColumns( reorderedColumn != null ? reorderedColumn : orderedColumns );
}
else {
final ArrayList<Column> orderedColumns = new ArrayList<>( userDefinedType.getColumnSpan() );
for ( String structColumnName : structColumnNames ) {
if ( !addColumns( orderedColumns, component, structColumnName ) ) {
throw new MappingException( "Couldn't find column [" + structColumnName + "] that was defined in @Struct(attributes) in the component [" + component.getComponentClassName() + "]" );
}
}
userDefinedType.reorderColumns( orderedColumns );
}
}
private static void addColumns(ArrayList<Column> orderedColumns, Value value) {
if ( value instanceof Component subComponent ) {
if ( subComponent.getAggregateColumn() == null ) {
for ( Property property : subComponent.getProperties() ) {
addColumns( orderedColumns, property.getValue() );
}
}
else {
orderedColumns.add( subComponent.getAggregateColumn() );
}
}
else {View on GitHub (pinned to fad1729dce)
Solutions
- Compare each @Struct attributes entry against the effective column names of the embeddable fields (@Column name if present, else the naming-strategy-derived name)
- Fix the typo or casing so names match exactly
- If the database struct name must stay, add @Column(name = "...") to the field to align it with the struct attribute
- Last resort: drop the attributes list and let ordering follow the default strategy
Example fix
// before: struct attribute name does not match any mapped column
@Embeddable
@Struct(name = "address", attributes = {"street", "zip"}) // 'zip' maps nothing
public class Address {
private String street;
@Column(name = "post_code")
private String postCode;
}
// after: names aligned
@Struct(name = "address", attributes = {"street", "post_code"}) Defensive patterns
Strategy: validation
Validate before calling
// Before boot: every @Struct attribute must match an effective column name
static List<String> structMismatches(Class<?> embeddable, PhysicalNamingStrategy ns) {
Set<String> cols = new HashSet<>();
for (Field f : embeddable.getDeclaredFields()) {
Column c = f.getAnnotation(Column.class);
cols.add(c != null && !c.name().isEmpty() ? c.name() : ns.toPhysicalColumnName(f.getName()));
}
return Arrays.stream(embeddable.getAnnotation(Struct.class).attributes())
.filter(a -> !cols.contains(a)).toList();
} Try / catch
try {
sessionFactory = metadata.buildSessionFactory();
} catch (MappingException e) {
if (e.getMessage().contains("that was defined in @Struct(attributes)")) {
throw new IllegalStateException("Struct attribute names out of sync with embeddable columns", e);
}
throw e;
} Prevention
- Keep @Struct(attributes) and @Column names in one place; update them together
- Write a unit test that cross-checks struct attribute names against mapped column names
- Avoid renaming struct fields casually - the database UDT definition must stay in sync too
When it happens
Trigger: A @Struct annotation whose attributes array contains a name that does not correspond to any mapped column of the embeddable - a typo, a different casing convention, or a field renamed via @Column after the struct attributes were written.
Common situations: Renaming embeddable fields or their @Column names without updating @Struct(attributes); adapting the Java model to a pre-existing database struct whose attribute spellings differ; case-sensitivity mismatches (USR_NAME vs usr_name) on case-sensitive DBs.
Related errors
- Dialect does not support structured array types: ${dialectCl
- Database does not support user-defined types (remove '@Struc
- Property '${property}' uses one-to-one mapping with mappedBy
- Property '${property}' uses *-to-many mapping with mappedBy
- Property '${property}' defines a collection table '${collect
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/0136c3b03c1c348c.
Report an issue: GitHub.