mybatis/mybatis-3 · error · ExecutorException

No setter found for the keyProperty '" + property + "' in "

Error message

No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + "."

What it means

Before writing the key value into the parameter object, setValue checks metaParam.hasSetter(property). If the insert's parameter object has no setter for the declared keyProperty, this ExecutorException naming the property and class is thrown. Unlike Jdbc3KeyGenerator's check, this one runs against the top-level parameter object for every keyProperty/keyColumn pair.

Source

Thrown at src/main/java/org/apache/ibatis/executor/keygen/SelectKeyGenerator.java:116

    if (keyColumns == null || keyColumns.length == 0) {
      // no key columns specified, just use the property names
      for (String keyProperty : keyProperties) {
        setValue(metaParam, keyProperty, metaResult.getValue(keyProperty));
      }
    } else {
      if (keyColumns.length != keyProperties.length) {
        throw new ExecutorException(
            "If SelectKey has key columns, the number must match the number of key properties.");
      }
      for (int i = 0; i < keyProperties.length; i++) {
        setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
      }
    }
  }

  private void setValue(MetaObject metaParam, String property, Object value) {
    if (!metaParam.hasSetter(property)) {
      throw new ExecutorException("No setter found for the keyProperty '" + property + "' in "
          + metaParam.getOriginalObject().getClass().getName() + ".");
    }
    metaParam.setValue(property, value);
  }
}

View on GitHub (pinned to 008069adb1)

Solutions

  1. Add a setter for the keyProperty on the parameter class
  2. Correct the property name in keyProperty to match the class's setter
  3. Use a mutable POJO as the insert parameter instead of an immutable one

Example fix

// before
class Order { private Long orderId; /* getters only */ }

// after
class Order { private Long orderId; public Long getOrderId() {...} public void setOrderId(Long id) { this.orderId = id; } }
Defensive patterns

Strategy: validation

Validate before calling

// Assert the parameter object can receive the key before mapping
MetaObject mo = configuration.newMetaObject(new Order());
for (String kp : new String[]{"orderId"}) {
  if (!mo.hasSetter(kp)) throw new IllegalStateException("missing setter: " + kp);
}

Prevention

When it happens

Trigger: <selectKey keyProperty="userId"> when the parameter class lacks setUserId; immutable parameter classes; misspelled or wrong-case property; keyProperty containing a prefix that does not resolve on this parameter object.

Common situations: Using Lombok @Value or builder-only classes as insert parameters, records, or renamed DTO fields without updating the mapper XML.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/da554b244501b351. Report an issue: GitHub.