MyBatis 多参数绑定报错:Parameter 'xxx' not found 的原因与修复

在 MyBatis Mapper 中传入多个参数时,如果 XML 使用的占位符名称无法和 Mapper 方法参数对应,常会出现下面的异常:

org.apache.ibatis.binding.BindingException: Parameter 'xxx' not found.
Available parameters are [arg1, arg0, param1, param2]

适用场景

  • Mapper 方法有两个或以上参数;
  • XML 中使用 #{id}、#{name} 等具名参数;
  • 未开启或未依赖 Java 编译参数名保留;
  • 使用注解指定参数名,但 XML 仍无法解析。

根因

MyBatis 不会自动把多个 Java 方法参数映射为 XML 中任意自定义名称。

当方法没有显式标注参数名时,MyBatis 通常暴露的是 arg0、arg1、param1、param2 这类名称。若 XML 使用 #{id},但 Mapper 方法中没有名为 id 的可识别参数,便会触发 BindingException。

推荐写法:使用 @Param 显式绑定

Mapper 方法:

List<Entity> selectByCondition(
        @Param("id") Long id,
        @Param("name") String name);

XML 中使用相同名称:

<select id="selectByCondition" resultType="Entity">
    SELECT id, name
    FROM example_table
    WHERE id = #{id}
      AND name = #{name}
</select>

关键要求是:@Param 的值和 XML 占位符必须完全一致,包括大小写。

常见检查点

  1. 多参数方法是否都使用了 @Param。
  2. XML 中的 #{...} 名称是否和 @Param 一致。
  3. @Param 是否来自正确的包:
import org.apache.ibatis.annotations.Param;
  1. Mapper 方法名和 XML 的 id 是否一致。
  2. 如果参数被封装为对象,则 XML 应使用对象属性名,而不是对象变量名。

例如:

List<Entity> selectByRequest(QueryRequest request);
WHERE id = #{id}

前提是 QueryRequest 中存在 id 属性。

验证方法

  • 启动后执行对应查询,确认不再出现 BindingException。
  • 开启 SQL 参数日志时,确认查询参数已按预期绑定。
  • 覆盖空值、空字符串和多个查询条件组合,确保动态 SQL 的条件名称保持一致。

可复用经验

对于多个独立参数,显式使用 @Param 是最直观、最稳定的做法。它能让 Mapper 方法签名与 XML 占位符形成清晰契约,也能减少因编译参数、框架版本或重构带来的隐式参数名问题。