hibernate/hibernate-orm · error · MappingException
Struct [%s] of class [%s] is defined by multiple components
Error message
Struct [%s] of class [%s] is defined by multiple components with different mappings [%s] and [%s] for column [%s]
What it means
The second stage of validateEqual for struct definitions sharing one name: matching columns must also agree on SQL type. If column X maps to varchar(255) in one component and to a Clob/varchar(10)/different type in the other, Hibernate throws this MappingException showing the struct name, component class, both SQL types, and the column.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java:412
throw new MappingException(
String.format(
"Struct [%s] is defined by multiple components %s with different number of mappings %d and %d",
udt1.getName(),
findComponentClasses(),
udt1.getColumnSpan(),
udt2.getColumnSpan()
)
);
}
final List<Column> missingColumns = new ArrayList<>();
for ( Column column1 : udt1.getColumns() ) {
final Column column2 = udt2.getColumn( column1 );
if ( column2 == null ) {
missingColumns.add( column1 );
}
else if ( !column1.getSqlType().equals( column2.getSqlType() ) ) {
throw new MappingException(
String.format(
"Struct [%s] of class [%s] is defined by multiple components with different mappings [%s] and [%s] for column [%s]",
udt1.getName(),
componentClassDetails.getName(),
column1.getSqlType(),
column2.getSqlType(),
column1.getCanonicalName()
)
);
}
}
if ( !missingColumns.isEmpty() ) {
throw new MappingException(
String.format(
"Struct [%s] is defined by multiple components %s but some columns are missing in [%s]: %s",
udt1.getName(),
findComponentClasses(),View on GitHub (pinned to fad1729dce)
Solutions
- Align the type mapping of the differing column in both components (same JDBC type, length, Lob usage)
- Preferably collapse both components into one canonical embeddable class
- If the databases/UDTs truly differ, rename one struct so the definitions stop colliding
Example fix
// before: same struct, same field, different SQL type
@Embeddable @Struct(name = "note")
public class NoteA { @Column(length = 100) String text; }
@Embeddable @Struct(name = "note")
public class NoteB { @Lob String text; } // CLOB vs varchar -> error
// after: identical mapping
@Embeddable @Struct(name = "note")
public class NoteA { @Column(length = 100) String text; }
@Embeddable @Struct(name = "note")
public class NoteB { @Column(length = 100) String text; } Defensive patterns
Strategy: validation
Validate before calling
// Before boot: embeddables sharing a struct name must agree on every column's SQL shape
static boolean structColumnTypesAgree(Class<?> a, Class<?> b) {
Map<String, Column> colsB = columnMap(b);
for (Map.Entry<String, Column> e : columnMap(a).entrySet()) {
Column other = colsB.get(e.getKey());
if (other == null) return false;
if (e.getValue().length() != other.length()
|| e.getValue().lob() != other.lob()) return false;
}
return colsB.keySet().equals(columnMap(a).keySet());
} Try / catch
try {
sessionFactory = metadata.buildSessionFactory();
} catch (MappingException e) {
if (e.getMessage().contains("different mappings")) {
throw new IllegalStateException("Diverging column types between components of one struct", e);
}
throw e;
} Prevention
- Maintain exactly one embeddable per database struct
- When a struct's column type changes, grep for every @Struct with that name
- Include column length/@Lob/enum mapping in code review for struct embeddables
When it happens
Trigger: Two embeddables with the same @Struct(name=...) declare the same field names but with different mapped types or column definitions - e.g. String vs @Lob String, different lengths, an enum mapped STRING vs ORDINAL, or different @JdbcTypeCode.
Common situations: Two teams mapping the same UDT independently; refactoring one embeddable's types without updating its twin; copy-paste divergence where a length or Lob annotation was added on one side only.
Related errors
- Database does not support user-defined types (remove '@Struc
- Struct [%s] is defined by multiple components %s with differ
- Struct [%s] is defined by multiple components %s but some co
- Dialect does not support structured array types: ${dialectCl
- Property '${property}' uses one-to-one mapping with mappedBy
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/672a918868ec783c.
Report an issue: GitHub.