hibernate/hibernate-orm · error · PropertyNotFoundException
Could not locate getter method for property '%s' of class '%
Error message
Could not locate getter method for property '%s' of class '%s'
What it means
Hibernate resolves mapped properties through JavaBean reflection. ReflectHelper.findGetterMethod walks the class, its superclasses, and all implemented interfaces looking for a public getFoo()/isFoo() accessor whose name matches the mapped property name. When no such method exists anywhere in the hierarchy, it throws PropertyNotFoundException at mapping time, meaning the mapping metadata names a property the Java class does not expose.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java:467
}
// check containerClass, and then its super types (if any)
while ( getter == null && checkClass != null ) {
if ( checkClass.equals( Object.class ) ) {
break;
}
else {
getter = getGetterOrNull( checkClass, propertyName );
// if no getter found yet, check all implemented interfaces
if ( getter == null ) {
getter = getGetterOrNull( checkClass.getInterfaces(), propertyName );
}
checkClass = checkClass.getSuperclass();
}
}
if ( getter == null ) {
throw new PropertyNotFoundException(
String.format(
Locale.ROOT,
"Could not locate getter method for property '%s' of class '%s'",
propertyName,
containerClass.getName()
)
);
}
ensureAccessibility( getter );
return getter;
}
private static Method getGetterOrNull(Class<?>[] interfaces, String propertyName) {
Method getter = null;
for ( int i = 0; getter == null && i < interfaces.length; ++i ) {
final var anInterface = interfaces[i];View on GitHub (pinned to fad1729dce)
Solutions
- Fix the property name in the mapping so it exactly matches an existing getX()/isX() method (case-sensitive, first letter uppercase).
- Add the missing public getter to the entity or component class (or one of its superclasses).
- Switch the class or property to field access with @Access(AccessType.FIELD) so no getter is required.
- If the accessor exists but is non-public or non-standard, make it public or expose a conventional JavaBean getter.
Example fix
// before: mapping expects a getter that does not exist
@Entity
@Access(AccessType.PROPERTY)
public class User {
private String emailAddress;
@Column(name = "email")
public String getEmail() { return emailAddress; } // mapping says "emial" -> PropertyNotFoundException
}
// after: mapping name matches the getter
@Column(name = "email")
public String getEmail() { return emailAddress; } // mapped as <property name="email"/> Defensive patterns
Strategy: validation
Validate before calling
static void verifyGetters(Class<?> entityClass, List<String> mappedPropertyNames) {
java.beans.BeanInfo info;
try {
info = java.beans.Introspector.getBeanInfo(entityClass);
} catch (java.beans.IntrospectionException e) {
throw new IllegalStateException("Cannot introspect " + entityClass.getName(), e);
}
java.util.Set<String> readable = new java.util.HashSet<>();
for (java.beans.PropertyDescriptor pd : info.getPropertyDescriptors()) {
if (pd.getReadMethod() != null) readable.add(pd.getName());
}
for (String name : mappedPropertyNames) {
if (!readable.contains(name)) {
throw new IllegalStateException("No getter for mapped property '" + name + "' on " + entityClass.getName());
}
}
} Type guard
static boolean hasGetter(Class<?> clazz, String property) {
try {
return new java.beans.PropertyDescriptor(property, clazz).getReadMethod() != null;
} catch (java.beans.IntrospectionException e) {
return false;
}
} Try / catch
try {
SessionFactory sf = metadata.buildSessionFactory();
} catch (org.hibernate.PropertyNotFoundException e) {
// message names the property and class; align the mapping name with a real getter or add the accessor
} Prevention
- Keep mapping property names and Java getters in lockstep; regenerate mappings after renaming fields.
- Prefer @Access(AccessType.FIELD) on entity classes without JavaBean accessors.
- Add a CI step that builds the SessionFactory so mapping/accessor drift fails the build, not production.
When it happens
Trigger: Building a SessionFactory where an hbm.xml <property name="..."> or a property-access (@Access(AccessType.PROPERTY)) attribute references a name that has no matching public getter on the class, superclasses, or interfaces. Also produced by direct calls to ReflectHelper.getGetter/findGetterMethod with a property name that has no accessor.
Common situations: Typo in the mapped property name versus the actual getter; renaming or removing getters during a refactor while mappings stay stale; non-public or unconventionally named accessors; property access on @Embeddable components without getters; mappings generated from one version of a class while a different version is deployed.
Related errors
- Could not locate setter method for property '%s' of class '%
- Class<?> '%s' declares both 'get' [%s] and 'is' [%s] variant
- Could not locate field for property named [" + containerJava
- Could not locate getter for property named [" + containerJav
- Could not locate field for property named [" + containerJava
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4efff4ef25bff72a.
Report an issue: GitHub.