hibernate/hibernate-orm · error · IllegalStateException

{mappedSuperclassTypeName} is not a supertype of {componentT

Error message

{mappedSuperclassTypeName} is not a supertype of {componentTypeName}

What it means

An IllegalStateException thrown by MetadataContext.getMappedSuperclassDomainType while processing @IdClass mappings: when an entity's id class component declares a MappedSuperclass, Hibernate resolves its domain type and verifies that the mapped-superclass Java type is actually assignable from the id class (mappedSuperclassClass.isAssignableFrom(componentClass)). If the @IdClass type does not sit below the mapped superclass that provided the id fields, the invariant is broken and JPA metamodel building fails with 'X is not a supertype of Y'.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java:619

				getJavaTypeRegistry().resolveManagedTypeDescriptor( componentClass ),
				getMappedSuperclassDomainType( idClassComponent, componentClass ),
				null,
				false,
				getJpaMetamodel()
		);
	}

	private <Y> MappedSuperclassDomainType<? super Y> getMappedSuperclassDomainType(
			Component idClassComponent, Class<Y> componentClass) {
		final var mappedSuperclass = idClassComponent.getMappedSuperclass();
		if ( mappedSuperclass == null ) {
			return null;
		}
		else {
			final var domainType = locateMappedSuperclassType( mappedSuperclass );
			final var mappedSuperclassClass = domainType.getJavaType();
			if ( !mappedSuperclassClass.isAssignableFrom( componentClass ) ) {
				throw new IllegalStateException(
						mappedSuperclassClass.getTypeName()
						+ " is not a supertype of " + componentClass.getTypeName()
				);
			}
			@SuppressWarnings("unchecked") // Safe, we just checked
			final var castDomainType = (MappedSuperclassDomainType<? super Y>) domainType;
			return castDomainType;
		}
	}

	private <X> void applyIdMetadata(MappedSuperclass mappingType, MappedSuperclassDomainType<X> jpaMappingType) {
		final var managedType = (ManagedDomainType<X>) jpaMappingType;
		final var attributeContainer = (AttributeContainer<X>) managedType;
		if ( mappingType.hasIdentifierProperty() ) {
			final var declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty();
			if ( declaredIdentifierProperty != null ) {
				final var attribute =
						(SingularPersistentAttribute<X, ?>)

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the @IdClass extend the same @MappedSuperclass (or otherwise be a subtype of it) that declares the id attributes
  2. Alternatively, move the id declarations out of the mapped superclass into each entity (or the id class) so no cross-hierarchy assignability is required
  3. Consider @EmbeddedId instead of @IdClass - it avoids the superclass/id-class alignment requirement entirely
  4. After fixing, rebuild the metamodel at startup (EntityManagerFactory creation) to confirm the invariant holds

Example fix

// before - IdClass does not extend the mapped superclass that owns the id
@MappedSuperclass
public abstract class BaseEntity { @Id Long id; }

@Entity
@IdClass(UserId.class)          // UserId only re-declares id
public class User extends BaseEntity { ... }

public class UserId implements Serializable { Long id; }

// after - align the hierarchies (or switch to @EmbeddedId)
public class UserId extends BaseEntity implements Serializable {}

// or avoid @IdClass entirely
@Entity
public class User extends BaseEntity { @EmbeddedId EmbeddedUserId id; }
Defensive patterns

Strategy: validation

Validate before calling

// Verify the @IdClass hierarchy aligns with the @MappedSuperclass that owns the id
Class<?> idClass = UserId.class;
Class<?> idOwningSuperclass = BaseEntity.class; // declared @MappedSuperclass carrying @Id
if ( !idOwningSuperclass.isAssignableFrom(idClass) ) {
    throw new IllegalStateException(idClass + " must extend " + idOwningSuperclass + " (id-class hierarchy mismatch)");
}

Type guard

static boolean idClassHierarchyAligned(Class<?> mappedSuperclass, Class<?> idClass) {
    return mappedSuperclass == null || mappedSuperclass.isAssignableFrom(idClass);
}

Try / catch

try {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
}
catch ( IllegalStateException e ) {
    if ( e.getMessage() != null && e.getMessage().endsWith("is not a supertype of") ) {
        throw new ConfigurationError("@IdClass must sit below the @MappedSuperclass that declares the id - " + e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An @IdClass whose class does not extend the @MappedSuperclass that declares the id attributes (e.g. a generic base @MappedSuperclass 'BaseEntity<T>' declares the id, but the @IdClass only re-declares fields instead of extending the same base); hierarchy refactors where entity inheritance and id-class inheritance were not kept parallel; mixed annotation/XML setups re-declaring the same id fields inconsistently.

Common situations: Generic repository base classes (@MappedSuperclass with @Id field) combined with @IdClass that duplicates the field instead of extending the base; upgrading Hibernate 5.x projects where this mismatch previously went unchecked; multi-module projects where the id class hierarchy diverged from the entity hierarchy.

Related errors


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