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
- Make the @IdClass extend the same @MappedSuperclass (or otherwise be a subtype of it) that declares the id attributes
- Alternatively, move the id declarations out of the mapped superclass into each entity (or the id class) so no cross-hierarchy assignability is required
- Consider @EmbeddedId instead of @IdClass - it avoids the superclass/id-class alignment requirement entirely
- 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
- Keep @IdClass inheritance parallel to entity @MappedSuperclass inheritance
- Consider @EmbeddedId to avoid id-class/superclass alignment constraints altogether
- After any hierarchy refactor, boot the persistence unit in a unit test
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
- Mapped superclass '{}' may not specify an '@Inheritance' map
- Attribute '${attribute}' is declared as an '@Id' or '@Embedd
- Attribute '" + memberDetails.getName() + "' is declared by '
- Root entity '<entityName>' is annotated '@DiscriminatorOptio
- Class '<className>' is not the root class of an entity inher
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7c07b7ed5cec1e16.
Report an issue: GitHub.