hibernate/hibernate-orm · error · UnsupportedOperationException
EntityPersister implementation '{className}' does not suppor
Error message
EntityPersister implementation '{className}' does not support 'NaturalIdLoader' What it means
EntityPersister.getNaturalIdLoader() backs the natural-id load API (session.byNaturalId(...), bySimpleNaturalId(...)). AbstractEntityPersister implements it; the interface default throws UnsupportedOperationException('EntityPersister implementation ... does not support NaturalIdLoader'), so persisters outside that hierarchy — custom implementations that do not override the method — fail the moment a natural-id query runs, regardless of whether @NaturalId is mapped.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java:597
y,
valueConsumer,
session
);
}
}
return span;
}
/**
* Determine whether this entity defines any lazy properties (when bytecode
* instrumentation is enabled).
*
* @return True if the entity has properties mapped as lazy; false otherwise.
*/
boolean hasLazyProperties();
default NaturalIdLoader<?> getNaturalIdLoader() {
throw new UnsupportedOperationException(
"EntityPersister implementation '" + getClass().getName()
+ "' does not support 'NaturalIdLoader'"
);
}
default MultiNaturalIdLoader<?> getMultiNaturalIdLoader() {
throw new UnsupportedOperationException(
"EntityPersister implementation '" + getClass().getName()
+ "' does not support 'MultiNaturalIdLoader'"
);
}
/**
* Load an instance of the persistent class.
*/
Object load(Object id, Object optionalObject, LockMode lockMode, SharedSessionContractImplementor session);
/**View on GitHub (pinned to fad1729dce)
Solutions
- Implement getNaturalIdLoader() (and getMultiNaturalIdLoader()) in the custom persister, modelling AbstractEntityPersister's implementation
- Remove the custom persister for entities that need natural-id access
- Use id-based loading (session.find / em.find) instead of the natural-id API for that entity
Example fix
// before
MyEntity e = session.bySimpleNaturalId(MyEntity.class).load("ABC"); // custom persister -> UnsupportedOperationException
// after
MyEntity e = session.find(MyEntity.class, id); // PK lookup works on any persister Defensive patterns
Strategy: validation
Validate before calling
EntityPersister p = sessionFactory.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor(Product.class);
if ( p.hasNaturalIdentifier()
&& p instanceof org.hibernate.persister.entity.AbstractEntityPersister ) {
Object loaded = session.byNaturalId(Product.class)
.using("code", code)
.load();
} Type guard
static boolean supportsNaturalIdLoad(EntityPersister persister) {
return persister.hasNaturalIdentifier()
&& persister instanceof org.hibernate.persister.entity.AbstractEntityPersister;
} Prevention
- Verify the persister type before using natural-id APIs on entities mapped with @Persister
- Cover natural-id load paths with integration tests for every entity using a custom persister
- Prefer em.find by primary key when a custom persister is unavoidable
When it happens
Trigger: session.byNaturalId(MyEntity.class).using("code", value).load() or session.bySimpleNaturalId(MyEntity.class).simpleLoad() against an entity whose persister is a custom EntityPersister implementation (persisterClass/@Persister) that does not override getNaturalIdLoader().
Common situations: Custom persisters for legacy integration; wrapper/decorating persisters added for instrumentation; unit tests with stub persisters; third-party persister providers.
Related errors
- EntityPersister implementation '{className}' does not suppor
- Entity '{name}' does not have a natural id
- EntityPersister implementation '{className}' does not suppor
- No fetch profile named '{}'
- Association '{propertyName}' marked as '@NaturalId' is also
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f2496f108f05d383.
Report an issue: GitHub.