hibernate/hibernate-orm · error · UnsupportedOperationException
Dialect does not support structured array types: ${dialectCl
Error message
Dialect does not support structured array types: ${dialectClassName} What it means
AggregateComponentBinder assigns a SQL type code when a struct aggregate (an @Struct embeddable) is mapped as a plural attribute (array or collection). It maps a preferred array code of SqlTypes.ARRAY to STRUCT_ARRAY and SqlTypes.TABLE to STRUCT_TABLE; any other preferred code - most commonly SqlTypes.JSON, which dialects without native arrays (MySQL/MariaDB family) prefer - has no structured equivalent, so an UnsupportedOperationException naming the dialect class is thrown.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentBinder.java:108
componentClassDetails,
inferredData.getPropertyName(),
context
)
);
}
}
private static <T> void registerDescriptor(Class<T> componentClass, TypeConfiguration typeConfiguration, String structName) {
typeConfiguration.getJavaTypeRegistry()
.resolveDescriptor( componentClass,
() -> new EmbeddableAggregateJavaType<>( componentClass, structName ) );
}
private static int getStructPluralSqlTypeCode(MetadataBuildingContext context) {
return switch ( context.getPreferredSqlTypeCodeForArray() ) {
case SqlTypes.ARRAY -> SqlTypes.STRUCT_ARRAY;
case SqlTypes.TABLE -> SqlTypes.STRUCT_TABLE;
default -> throw new UnsupportedOperationException(
"Dialect does not support structured array types: "
+ context.getMetadataCollector().getDatabase()
.getDialect().getClass().getName()
);
};
}
private static QualifiedName determineStructName(
PropertyData inferredData,
ClassDetails returnedClassOrElement,
MetadataBuildingContext context) {
final var memberDetails = inferredData.getAttributeMember();
if ( memberDetails != null ) {
final var struct = memberDetails.getDirectAnnotationUsage( Struct.class );
if ( struct != null ) {
return toQualifiedName( struct, context );
}
}View on GitHub (pinned to fad1729dce)
Solutions
- Remove @Struct from the embeddable so elements are no longer bound to a structured SQL type
- Run against a database/dialect whose preferred array code is ARRAY (e.g. PostgreSQL, Oracle, DB2)
- Undo the JSON preference: remove the hibernate.type.preferred_array_jdbc_type setting or set it to ARRAY (SqlTypes.ARRAY) where struct arrays must work
- Remap the plural attribute as a plain basic array (e.g. List<String> or a JSON-mapped type) instead of an aggregate struct
Example fix
// before: struct aggregate inside a plural attribute on a JSON-array dialect
@Embeddable
@Struct(name = "address")
public class Address { ... }
@Entity
public class Customer {
@Array // needs STRUCT_ARRAY/STRUCT_TABLE
private List<Address> addresses;
}
// with hibernate.type.preferred_array_jdbc_type = JSON (or MySQL dialect) -> UnsupportedOperationException
// after: drop the struct binding, or target an ARRAY dialect
@Embeddable // no @Struct: stored as plain aggregate/JSON
public class Address { ... }
// or keep @Struct only when the dialect prefers SqlTypes.ARRAY (PostgreSQL etc.) Defensive patterns
Strategy: validation
Validate before calling
// Before defining struct arrays: assert the effective array code supports structures
static boolean dialectSupportsStructArrays(Dialect dialect) {
int code = dialect.getPreferredSqlTypeCodeForArray();
return code == SqlTypes.ARRAY || code == SqlTypes.TABLE;
}
// In a test: fail fast with a clear message instead of a boot crash
Assume.assumeTrue("Dialect cannot store struct arrays",
dialectSupportsStructArrays(actualDialect())); Try / catch
try {
sessionFactory = metadata.buildSessionFactory();
} catch (UnsupportedOperationException e) {
if (e.getMessage().startsWith("Dialect does not support structured array types")) {
throw new IllegalStateException("Struct aggregates in arrays are not usable with this database - "
+ "remove @Struct or switch the dialect", e);
}
throw e;
} Prevention
- Keep struct-array mappings behind a database profile; guard tests with a capability assumption
- Do not set a global preferred array JDBC type without checking it also fits aggregate mappings
- Document which databases each entity model supports when using @Struct
When it happens
Trigger: Mapping List<StructEmbeddable> or @Array on a @Struct-annotated embeddable while the effective preferred array type code (dialect default, or hibernate.type.preferred_array_jdbc_type / MetadataBuilder.applyPreferredSqlTypeCodeForArray) is JSON or another non-ARRAY/TABLE code.
Common situations: Running the same mapping on PostgreSQL in production but MySQL/H2 in tests; setting a global preferred-array JSON setting for basic arrays and forgetting it also affects struct arrays; migrating from Hibernate 6 to 7 where structured array handling was tightened.
Related errors
- Property '${property}' uses one-to-one mapping with mappedBy
- Property '${property}' uses *-to-many mapping with mappedBy
- Property '${property}' defines a collection table '${collect
- Database does not support user-defined types (remove '@Struc
- Couldn't find column [${structColumnName}] that was defined
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/8e95c5fff09bdb41.
Report an issue: GitHub.