hibernate/hibernate-orm · error · EntityTypeException
Could not resolve entity class '{}'
Error message
Could not resolve entity class '{}' What it means
JpaMetamodelImpl throws EntityTypeException('Could not resolve entity class') when asked for an EntityDomainType for a Java class that is neither itself a registered entity nor has any registered entity subclass (createPolymorphicRootDescriptor finds zero matching descriptors). This is the JPA metamodel/SQM entry point — entity(Class), criteria roots, and graph creation all funnel through it.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java:572
if ( proxyEntityName != null ) {
return entity( proxyEntityName );
}
// otherwise, try to handle it as a polymorphic reference
final var polymorphicDomainType =
polymorphicEntityReferenceMap.get( javaType );
if ( polymorphicDomainType != null ) {
return polymorphicDomainType;
}
else {
final var polymorphicRootDescriptor =
createPolymorphicRootDescriptor( javaType );
if ( polymorphicRootDescriptor != null ) {
return polymorphicRootDescriptor;
}
}
throw new EntityTypeException(
"Could not resolve entity class '" + javaType.getName() + "'",
javaType.getName()
);
}
private <T> @Nullable SqmPolymorphicRootDescriptor<T> createPolymorphicRootDescriptor(Class<T> javaType) {
// create a set of descriptors that should be used to build the polymorphic EntityDomainType
final Set<EntityDomainType<? extends T>> matchingDescriptors = new HashSet<>();
for ( var managedType : managedTypeByName.values() ) {
if ( managedType.getPersistenceType() == Type.PersistenceType.ENTITY
// see if we should add EntityDomainType as one of the matching descriptors.
&& javaType.isAssignableFrom( managedType.getJavaType() ) ) {
// The queried type is assignable from the type of the current entity type.
// We should add it to the collecting set of matching descriptors. It should
// be added aside from a few cases...
// If the managed type has a supertype and the java type is assignable from the super type,
// do not add the managed type as the supertype itself will get added and the initializersView on GitHub (pinned to fad1729dce)
Solutions
- Pass a class that is annotated @Entity and mapped in the same persistence unit
- For polymorphic queries over a hierarchy, make the common supertype an @Entity with an @Inheritance strategy, or query any @Entity subclass — Hibernate builds a polymorphic descriptor when at least one entity subclass is assignable
- For interfaces, add at least one @Entity implementation or map the interface as a proxy (@Proxy) so it resolves
- Double-check which persistence unit / entity scan the class is actually in
Example fix
// before
CriteriaQuery<Auditable> q = cb.createQuery(Auditable.class); // Auditable is a plain interface
Root<Auditable> r = q.from(Auditable.class); // throws EntityTypeException
// after
@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Auditable { ... }
// then query the mapped hierarchy root
CriteriaQuery<Auditable> q = cb.createQuery(Auditable.class);
Root<Auditable> r = q.from(Auditable.class); Defensive patterns
Strategy: validation
Validate before calling
<T> EntityType<T> entityOrThrow(Metamodel metamodel, Class<T> cls) {
return metamodel.getEntities().stream()
.filter(e -> cls.equals(e.getJavaType()))
.map(e -> (EntityType<T>) e)
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(
"Not a mapped entity: " + cls + ". Known: " +
metamodel.getEntities().stream().map(Type::getJavaType).toList()));
}
// use: entityOrThrow(emf.getMetamodel(), cls) instead of emf.getMetamodel().entity(cls) Type guard
static boolean isResolvableEntity(Metamodel metamodel, Class<?> cls) {
if (cls.isAnnotationPresent(jakarta.persistence.Entity.class)) return true;
// polymorphic fallback: at least one entity subclass assignable
return metamodel.getEntities().stream().anyMatch(e -> cls.isAssignableFrom(e.getJavaType()));
} Try / catch
try {
EntityType<X> t = emf.getMetamodel().entity(cls);
} catch (jakarta.persistence.metamodel.TypeNotFoundException | EntityTypeException e) { // Hibernate: org.hibernate.metamodel.EntityTypeException
throw new IllegalArgumentException(cls + " is not an entity in this persistence unit; fix the query domain type", e);
} Prevention
- Use typed criteria roots (cb.createQuery(Entity.class).from(Entity.class)) so non-entity roots fail at compile time
- Constrain generic repository type parameters with an @Entity marker bound
- In multi-PU apps, assert expected entities exist per factory at startup: metamodel.getEntities() vs a checklist
When it happens
Trigger: Calling emf.getMetamodel().entity(NonEntity.class) or criteriaBuilder.createQuery(X.class).from(X.class) where X is a DTO, @MappedSuperclass, or interface with no @Entity implementors; passing a class that lives in another persistence unit; passing java.lang.Object or a projection class as the query domain.
Common situations: Developer expects @MappedSuperclass or a plain interface to behave like a polymorphic @Entity root; a query root class was refactored into a DTO; the class is mapped in a different EntityManagerFactory (multi-PU setup); the entity was excluded from scanning.
Related errors
- Non-terminal property path did not reference FetchableContai
- Unknown attribute: {}
- Expecting Component for id mapping with no id-attribute
- {mappedSuperclassTypeName} is not a supertype of {componentT
- Encountered multiple component mappings for the same java cl
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/9fad701e2af22829.
Report an issue: GitHub.