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

  1. Compare each @Struct attributes entry against the effective column names of the embeddable fields (@Column name if present, else the naming-strategy-derived name)
  2. Fix the typo or casing so names match exactly
  3. If the database struct name must stay, add @Column(name = "...") to the field to align it with the struct attribute
  4. 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

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


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