hibernate/hibernate-orm · error · UnknownEntityTypeException
{uee.getMessage()} ('{entityClass.getSimpleName()}' does not
Error message
{uee.getMessage()} ('{entityClass.getSimpleName()}' does not belong to this persistence unit|is not annotated '@Entity') What it means
When SessionImpl.getEntityPersister cannot resolve an entity class, it retries and finally rethrows UnknownEntityTypeException with a diagnostic hint: the class either is not annotated @Entity or is not part of this persistence unit. The class-level check ('does not belong to this persistence unit' vs 'is not annotated') distinguishes a missing annotation from a class mapped elsewhere (different persistence unit or classloader).
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java:1606
// not given the opportunity to resolve a subclass entity name.
// This allows the (we assume custom) interceptor the ability to
// influence this decision if we were not able to based on the
// given entityName
try {
return requireEntityPersister( entityName )
.getSubclassEntityPersister( entity, getFactory() );
}
catch ( UnknownEntityTypeException uee ) {
try {
return getEntityPersister( null, entity );
}
catch ( HibernateException e ) {
final var entityClass = entity.getClass();
final String problem =
entityClass.isAnnotationPresent( Entity.class )
? "does not belong to this persistence unit"
: "is not annotated '@Entity'";
throw new UnknownEntityTypeException(
uee.getMessage()
+ " ('" + entityClass.getSimpleName() + "' " + problem + ")",
e
);
}
}
}
}
// not for internal use:
@Override
@Nullable
public Object getIdentifier(@Nonnull Object object) {
checkOpen();
checkTransactionSyncStatus();
//noinspection ConstantValue
if ( object == null ) {View on GitHub (pinned to fad1729dce)
Solutions
- Annotate the class with @Entity (jakarta.persistence.Entity) and give it an @Id — a missing id yields a different error later
- Add the class to the persistence unit: persistence.xml <class> entry, Spring Boot @EntityScan of its package, or Configuration.addAnnotatedClass()
- If multiple persistence units exist, perform the operation with the EntityManager/SessionFactory that actually maps the class
- Check the import: use jakarta.persistence.Entity (not javax) and ensure only one copy of the class is on the classpath/module path
Example fix
// before
public class CustomerDto { ... } // no @Entity
session.persist(customerDto); // UnknownEntityTypeException: not annotated '@Entity'
// after
@Entity
public class Customer {
@Id @GeneratedValue
private Long id;
// ...
}
session.persist(customer); Defensive patterns
Strategy: validation
Validate before calling
static boolean isManaged(SessionFactory sf, Class<?> clazz) {
try {
sf.getJpaMetamodel().entity(clazz);
return true;
} catch (IllegalArgumentException e) {
return false; // not mapped in this persistence unit
}
}
if (isManaged(sessionFactory, obj.getClass())) {
session.persist(obj);
} else {
throw new IllegalArgumentException("Not an entity of this persistence unit: " + obj.getClass());
} Type guard
static Optional<EntityType<?>> asEntity(SessionFactory sf, Class<?> c) {
try {
return Optional.of(sf.getJpaMetamodel().entity(c));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
} Try / catch
try {
session.persist(obj);
} catch (UnknownEntityTypeException e) {
throw new IllegalArgumentException(
"Class '" + obj.getClass().getName()
+ "' is not mapped in this persistence unit "
+ "(missing @Entity or wrong persistence unit)", e);
} Prevention
- Keep DTO and entity packages separate so unmapped types never reach session operations
- With multiple persistence units, route by entity package to the matching EntityManagerFactory
- Verify Spring @EntityScan / persistence.xml <class> entries cover every entity package
- After jakarta migration, remove javax.persistence leftovers so @Entity annotations resolve consistently
When it happens
Trigger: Passing an object to session operations (persist, merge, lock, refresh) whose class is not mapped in the factory that owns the session: a DTO or value class, a class annotated only with @Embeddable/MappedSuperclass, or an @Entity that lives in a different persistence unit. Also classloader splits in application servers serving two copies of the class.
Common situations: Mixing DTOs and entities and accidentally persisting a DTO; multiple persistence units (orders vs users) and an entity saved via the wrong EMF; Spring entity scanning missing a package (@EntityScan too narrow); JPMS/WildFly module classloader differences making the same class name loaded twice; jakarta vs javax @Entity import mixing after migration.
Related errors
- Entity '<entityName>' is not audited
- Entity '<entityName>' is not audited
- '@AttributeAccessor' annotation must specify a 'strategy'
- Unable to check validity of passed ValidatorFactory
- Could not locate method needed for ValidatorFactory validati
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/234ff28f83d60c7e.
Report an issue: GitHub.