hibernate/hibernate-orm · error · HibernateException
%s methods of lazy classes cannot be final: %s#%s
Error message
%s methods of lazy classes cannot be final: %s#%s
What it means
A HibernateException raised at bootstrap by validateGetterSetterMethodProxyability inside EntityRepresentationStrategyPojoStandard: when an entity is mapped as lazy/proxyable, Hibernate must be able to override the access methods of its attributes, so a final getter or setter makes proxy generation impossible. The message states 'Getter'/'Setter' methods of lazy classes cannot be final and names the declaring class and method.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java:382
return identifierPropertyAccess;
}
else {
final var propertyAccess = propertyAccessMap.get( bootAttributeDescriptor.getName() );
if ( propertyAccess != null ) {
return propertyAccess;
}
else if ( mapsIdRepresentationStrategy != null ) {
return mapsIdRepresentationStrategy.resolvePropertyAccess( bootAttributeDescriptor );
}
else {
return null;
}
}
}
private static void validateGetterSetterMethodProxyability(String getterOrSetter, Method method ) {
if ( method != null && isFinal( method.getModifiers() ) ) {
throw new HibernateException(
String.format(
"%s methods of lazy classes cannot be final: %s#%s",
getterOrSetter,
method.getDeclaringClass().getName(),
method.getName()
)
);
}
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Remove 'final' from the reported getter/setter (and from the class if it is final) so the proxy can subclass it
- For Kotlin, apply the all-open compiler plugin with the JPA targets (@Entity, @MappedSuperclass, @Embeddable) so classes and members are generated open
- Alternatively disable proxy-based laziness for this entity with @Proxy(lazy = false) if you accept eager loading
- Re-run SessionFactory creation - the validation fails fast at startup
Example fix
// Kotlin - before: final by default
@Entity
class Person(@get:Column val name: String) // getter is final -> HibernateException
// Kotlin - after: all-open plugin makes @Entity classes open
// build.gradle.kts: plugins { kotlin("plugin.jpa") version "..." }
@Entity
class Person(@get:Column open val name: String)
// Java - before/after
public final String getName() { ... } // -> remove 'final'
public String getName() { ... } Defensive patterns
Strategy: validation
Validate before calling
// Fail fast if a lazy-mapped entity has final accessors
for ( EntityType<?> t : emf.getMetamodel().getEntities() ) {
if ( isLazyMapped(t) ) {
for ( java.lang.reflect.Method m : t.getJavaType().getMethods() ) {
if ( ( m.getName().startsWith("get") || m.getName().startsWith("set") )
&& Modifier.isFinal(m.getModifiers()) ) {
throw new IllegalStateException("Final accessor blocks proxy: " + m);
}
}
}
} Type guard
static boolean proxyableAccessor(Method m) { return !Modifier.isFinal(m.getModifiers()); } Try / catch
try {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu");
}
catch ( org.hibernate.HibernateException e ) {
if ( e.getMessage() != null && e.getMessage().contains("cannot be final") ) {
throw new ConfigurationError("Remove 'final' from the named accessor or disable @Proxy lazy - " + e.getMessage(), e);
}
throw e;
} Prevention
- Never mark getters/setters of lazy/proxyable entities final (and avoid final entity classes)
- Kotlin projects: apply the kotlin-alopen/JPA plugin so @Entity members are open
- When introducing lazy proxying onto existing models, scan accessors for 'final' first
When it happens
Trigger: An entity with lazy=true/@Proxy(lazy=true) whose attribute getter or setter is declared final; Kotlin entity classes and properties, which are final by default unless marked open or compiled with the kotlin-allopen compiler plugin; Java classes hardened with 'final' on accessors for immutability.
Common situations: Introducing Kotlin entities without the kotlin.plugin.jpa/all-open plugin; adding 'final' to accessors during an immutability refactor; bytecode-obfuscated or code-generated models with final accessors; enabling lazy proxying on previously eagerly-loaded hierarchies.
Related errors
- proxy must be either an interface, or the class itself: {}
- No row with the given identifier exists for entity " + infoS
- queued clear cannot be used with orphan delete
- queued clear cannot be used with orphan delete
- queued clear cannot be used with orphan delete
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/74aac56b2455378d.
Report an issue: GitHub.