mybatis/mybatis-3 · error · ReflectionException
There is no setter for property named '{}' in '{}'
Error message
There is no setter for property named '{}' in '{}' What it means
Reflector.getSetInvoker(propertyName) throws when the class has no setter registered for that property (setMethods map has no entry). MyBatis calls it while populating result objects or applying parameter settings, so every mapped property needs a writable setter.
Source
Thrown at src/main/java/org/apache/ibatis/reflection/Reflector.java:381
public Class<?> getType() {
return clazz;
}
public Constructor<?> getDefaultConstructor() {
if (defaultConstructor != null) {
return defaultConstructor;
}
throw new ReflectionException("There is no default constructor for " + clazz);
}
public boolean hasDefaultConstructor() {
return defaultConstructor != null;
}
public Invoker getSetInvoker(String propertyName) {
Invoker method = setMethods.get(propertyName);
if (method == null) {
throw new ReflectionException("There is no setter for property named '" + propertyName + "' in '" + clazz + "'");
}
return method;
}
public Invoker getGetInvoker(String propertyName) {
Invoker method = getMethods.get(propertyName);
if (method == null) {
throw new ReflectionException("There is no getter for property named '" + propertyName + "' in '" + clazz + "'");
}
return method;
}
/**
* Gets the type for a property setter.
*
* @param propertyName
* - the name of the property
*View on GitHub (pinned to 008069adb1)
Solutions
- Add a standard setter setProperty(...) to the target class.
- Fix the property name in <result property="..."> to match the bean (case-insensitive lookup must still resolve).
- For immutable classes, switch to <constructor> mapping so values go through the constructor instead of setters.
Example fix
// before
class User { private final String name; User(String name){this.name=name;} }
<!-- resultMap: <result property="name" column="name"/> -->
// after
<resultMap id="u" type="User">
<constructor><arg column="name" javaType="string"/></constructor>
</resultMap> Defensive patterns
Strategy: validation
Validate before calling
Reflector ref = new Reflector(User.class); String[] writable = ref.getSetablePropertyNames(); // ensure every mapped property appears here
Type guard
boolean hasSetter(Class<?> c, String prop) {
return Arrays.asList(new Reflector(c).getSetablePropertyNames()).contains(prop.toUpperCase(Locale.ROOT));
} Prevention
- Map only writable properties in resultMaps; route immutable values through <constructor>.
- Keep bean property names and column-to-property mappings in one naming convention.
When it happens
Trigger: A resultMap maps a property (or automapping finds a column matching a field) whose class exposes no setX(...) method — final fields, read-only properties, or a property-name typo in the mapping.
Common situations: Immutable DTOs with final fields; property name case/spelling mismatch between column-toProperty mapping and the bean; using a getter-only property like 'id' generated by a sequence.
Related errors
- Error in result map '{resultMapId}'. Failed to find a constr
- Error instantiating {} with invalid types ({}) or values ({}
- Could not set property '{}' of '{}' with value '{}' Cause: {
- Error creating instance. Cause: {cause}
- Could not find a parent resultMap with id '{extend}'
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/8cac047586511d5b.
Report an issue: GitHub.