mybatis/mybatis-3 · error · BindingException
Mapper method '{name}' has an unsupported return type: {retu
Error message
Mapper method '{name}' has an unsupported return type: {returnType} What it means
rowCountResult() converts the row-count int returned by INSERT/UPDATE/DELETE into the mapper method's return type. Only void, Integer/int, Long/long, and Boolean/boolean are supported (boolean means 'rowCount > 0'). Any other declared return type on a DML mapper method triggers this BindingException.
Source
Thrown at src/main/java/org/apache/ibatis/binding/MapperMethod.java:117
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ "' attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
private Object rowCountResult(int rowCount) {
final Object result;
if (method.returnsVoid()) {
result = null;
} else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
result = rowCount;
} else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
result = (long) rowCount;
} else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
result = rowCount > 0;
} else {
throw new BindingException(
"Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType());
}
return result;
}
private void executeWithResultHandler(SqlSession sqlSession, Object[] args) {
MappedStatement ms = sqlSession.getConfiguration().getMappedStatement(command.getName());
if (!StatementType.CALLABLE.equals(ms.getStatementType())
&& void.class.equals(ms.getResultMaps().get(0).getType())) {
throw new BindingException(
"method " + command.getName() + " needs either a @ResultMap annotation, a @ResultType annotation,"
+ " or a resultType attribute in XML so a ResultHandler can be used as a parameter.");
}
Object param = method.convertArgsToSqlCommandParam(args);
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
sqlSession.select(command.getName(), param, rowBounds, method.extractResultHandler(args));
} else {View on GitHub (pinned to 008069adb1)
Solutions
- Change the DML mapper method return type to int/Integer, long/Long, boolean/Boolean, or void
- If you need the generated key, accept it via an @Options(useGeneratedKeys=true, keyProperty=...) parameter object instead of a return value
- Move the data-retrieval concern to a separate <select> method
Example fix
// before String updateUser(User u); // after int updateUser(User u); // or boolean updateUser(User u);
Defensive patterns
Strategy: validation
Validate before calling
for (Method m : UserMapper.class.getMethods()) {
Class<?> rt = m.getReturnType();
boolean dmlOk = rt == void.class || rt == int.class || rt == Integer.class
|| rt == long.class || rt == Long.class || rt == boolean.class || rt == Boolean.class;
// assert dmlOk for methods bound to insert/update/delete statements
} Prevention
- Keep DML mapper methods to int/long/boolean/void returns
- Retrieve generated keys via keyProperty on the parameter object, not via exotic return types
When it happens
Trigger: Declaring 'String updateUser(User u)' or 'List<Integer> insert(...)' on a method bound to an <insert>/<update>/<delete> statement; returning a custom POJO from a DML statement without useGeneratedKeys/resultMap mechanisms that go through a different path.
Common situations: Copying a SELECT method signature onto a DML statement; wanting to return the generated key typed as something other than the supported set.
Related errors
- Unknown execution method for: {name}
- Mapper method '{name}' attempted to return null from a metho
- method {name} needs either a @ResultMap annotation, a @Resul
- Parameter '{key}' not found. Available parameters are {keySe
- Invalid bound statement (not found): {mapperInterface}.{meth
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/e7ddc922c30531e8.
Report an issue: GitHub.