hibernate/hibernate-orm · error · MappingException

Basic array has element type '" + componentJavaType.getTypeN

Error message

Basic array has element type '" + componentJavaType.getTypeName() + "' which is not a known basic type (attribute is not annotated '@ElementCollection', '@OneToMany', or '@ManyToMany')

What it means

Thrown when Hibernate must pick a JDBC type for a basic array attribute (AbstractArrayJavaType.getRecommendedJdbcType) but the element's JavaType is UnknownBasicJavaType - meaning the component class has no registered basic type. The message reminds you that non-basic element collections must be mapped as @ElementCollection/@OneToMany/@ManyToMany, not as plain arrays.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java:44

public abstract class AbstractArrayJavaType<T, E> extends AbstractClassJavaType<T>
		implements BasicPluralJavaType<E> {

	private final JavaType<E> componentJavaType;

	public AbstractArrayJavaType(Class<T> clazz, JavaType<E> baseDescriptor, MutabilityPlan<T> mutabilityPlan) {
		super( clazz, mutabilityPlan );
		this.componentJavaType = baseDescriptor;
	}

	@Override
	public JavaType<E> getElementJavaType() {
		return componentJavaType;
	}

	@Override
	public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
		if ( componentJavaType instanceof UnknownBasicJavaType) {
			throw new MappingException("Basic array has element type '"
					+ componentJavaType.getTypeName()
					+ "' which is not a known basic type"
					+ " (attribute is not annotated '@ElementCollection', '@OneToMany', or '@ManyToMany')");
		}
		// Always determine the recommended type to make sure this is a valid basic java type
		final var recommendedComponentJdbcType = componentJavaType.getRecommendedJdbcType( indicators );
		final var typeConfiguration = indicators.getTypeConfiguration();
		return typeConfiguration.getJdbcTypeRegistry()
				.resolveTypeConstructorDescriptor(
						indicators.getPreferredSqlTypeCodeForArray( recommendedComponentJdbcType.getDefaultSqlTypeCode() ),
						typeConfiguration.getBasicTypeRegistry().resolve( componentJavaType, recommendedComponentJdbcType ),
						ColumnTypeInformation.EMPTY
				);
	}

	@Override
	public boolean isWider(JavaType<?> javaType) {
		// Support binding single element value

View on GitHub (pinned to fad1729dce)

Solutions

  1. Annotate the field with @ElementCollection (targetClass = element type) so it is mapped as a collection, not a basic array
  2. Change the element type to a known basic type (String, Integer, UUID, enum with @Enumerated, ...)
  3. Register a JavaType/BasicType for the custom element class via @JavaTypeRegistration on the entity or a TypeContributor
  4. Map the array explicitly with @JdbcTypeCode(SqlTypes.ARRAY) plus a registered element type

Example fix

// before
@Entity
public class Doc {
    private Tag[] tags; // Tag is not a known basic type -> MappingException
}
// after
@Entity
public class Doc {
    @ElementCollection(targetClass = String.class)
    @Column(name = "tags")
    private String[] tags;
}
// or: map Tag as a basic type via @JavaTypeRegistration and keep Tag[] with @JdbcTypeCode(SqlTypes.ARRAY)
Defensive patterns

Strategy: validation

Validate before calling

// in a @PrePersist/@PreUpdate-free mapping test (or bootstrap check):
// assert every array-typed persistent field has a basic element type or collection annotations
for (Field f : entityClass.getDeclaredFields()) {
    Class<?> elem = f.getType().getComponentType();
    if (elem != null && !isBasicType(elem)
            && !f.isAnnotationPresent(ElementCollection.class)) {
        throw new MappingException("Unannotated array of non-basic type: " + f);
    }
}

Type guard

static boolean isKnownBasicElement(Class<?> c) {
    return c.isPrimitive() || c == String.class || c.isEnum()
        || Number.class.isAssignableFrom(c)
        || java.time.temporal.Temporal.class.isAssignableFrom(c);
}

Try / catch

try {
    sessionFactory = new MetadataSources(registry).addAnnotatedClass(Doc.class)
            .buildMetadata().buildSessionFactory();
} catch (MappingException e) {
    if (String.valueOf(e.getMessage()).contains("not a known basic type")) {
        // annotate as @ElementCollection or register a JavaType for the element class
    } else throw e;
}

Prevention

When it happens

Trigger: An entity field like MyCustomType[] values or List<SomeEmbeddable> mapped as a basic array (dialect supports arrays, no collection annotations present) where the element class is not a known basic type; e.g. arrays of enums with custom mapping, arrays of Value Objects, or embeddables without @ElementCollection.

Common situations: Migrating to Hibernate 6/7 where basic array support was introduced and unannotated array fields stopped being treated as element collections; PostgreSQL array columns of custom types; forgetting @ElementCollection on a List<embeddable> field; element type lacking a BasicType registration.

Related errors


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