{"record":{"id":"f630821bf10340dd","repo":"mybatis/mybatis-3","slug":"there-is-no-getter-for-property-named-in","errorCode":null,"errorMessage":"There is no getter for property named '{}' in '{}'","messagePattern":"There is no getter for property named '(.+?)' in '(.+?)'","errorType":"exception","errorClass":"ReflectionException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/reflection/Reflector.java","lineNumber":389,"sourceCode":"    throw new ReflectionException(\"There is no default constructor for \" + clazz);\n  }\n\n  public boolean hasDefaultConstructor() {\n    return defaultConstructor != null;\n  }\n\n  public Invoker getSetInvoker(String propertyName) {\n    Invoker method = setMethods.get(propertyName);\n    if (method == null) {\n      throw new ReflectionException(\"There is no setter for property named '\" + propertyName + \"' in '\" + clazz + \"'\");\n    }\n    return method;\n  }\n\n  public Invoker getGetInvoker(String propertyName) {\n    Invoker method = getMethods.get(propertyName);\n    if (method == null) {\n      throw new ReflectionException(\"There is no getter for property named '\" + propertyName + \"' in '\" + clazz + \"'\");\n    }\n    return method;\n  }\n\n  /**\n   * Gets the type for a property setter.\n   *\n   * @param propertyName\n   *          - the name of the property\n   *\n   * @return The Class of the property setter\n   */\n  public Class<?> getSetterType(String propertyName) {\n    Class<?> clazz = setTypes.getOrDefault(propertyName, nullEntry).getValue();\n    if (clazz == null) {\n      throw new ReflectionException(\"There is no setter for property named '\" + propertyName + \"' in '\" + clazz + \"'\");\n    }\n    return clazz;","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/reflection/Reflector.java#L371-L407","documentation":"Reflector.getGetInvoker(propertyName) throws when no getter is registered for the property (getMethods map has no entry). MyBatis reads getters when extracting parameter values for #{} placeholders, evaluating OGNL in dynamic SQL, and building cache keys.","triggerScenarios":"Referencing #{prop} in SQL where the parameter object has no getProp()/isProp() accessor; <if test=\"prop != null\"> against a write-only or missing property; property name typo.","commonSituations":"Parameter DTO missing a getter (field-only access); misspelled placeholder vs. bean property; boolean property referenced as getProp instead of isProp and only the field exists; Lombok @Getter omitted.","solutions":["Add a standard getter getProperty() (or isProperty for booleans) to the parameter class.","Correct the property name in #{} or the OGNL test expression to match an actual readable property.","For maps, pass a Map parameter instead of a bean, or use @Param names so properties resolve differently."],"exampleFix":"<!-- before -->\n<select id=\"find\" parameterType=\"User\">SELECT * FROM t WHERE name = #{name}</select>\nclass User { private String name; }\n<!-- after -->\nclass User { private String name; public String getName(){return name;} }","handlingStrategy":"validation","validationCode":"Reflector ref = new Reflector(User.class);\nString[] readable = ref.getGetablePropertyNames(); // every #{prop} / test=\"prop\" must appear here","typeGuard":"boolean hasGetter(Class<?> c, String prop) {\n  return Arrays.asList(new Reflector(c).getGetablePropertyNames()).contains(prop.toUpperCase(Locale.ROOT));\n}","tryCatchPattern":null,"preventionTips":["Use Lombok @Getter/@Setter (or records where supported) so accessors never drift from fields.","For optional bindings, prefer Map or @Param parameters over beans with partial accessors."],"tags":["mybatis","reflection","getter","ognl","parameters"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}