必须使用@Param注解的场景是Mapper接口方法有两个及以上非Bean类型的参数时,否则MyBatis无法识别参数名导致BindingException;每个参数需用@Param("name")显式命名,且SQL中#{name}必须与之严格一致。

在 MyBatis 中,当方法有多个参数时,MyBatis 默认无法识别每个参数的含义,会将它们封装为 Map,但 key 是 arg0、arg1 或 param1、param2(取决于版本),容易出错或可读性差。使用 @Param 注解就是为每个参数显式命名,让 XML 或注解 SQL 中能准确引用。
什么时候必须用 @Param
当 Mapper 接口方法有两个及以上非 Bean 类型的参数(比如 String、int、Long 等基本类型或包装类)时,MyBatis 无法自动推断参数名,必须加 @Param,否则 SQL 中 #{xxx} 找不到对应 key,抛出 org.apache.ibatis.binding.BindingException。
- ✅ 正确:多个简单参数 → 每个都加
@Param("name") - ❌ 错误:只给部分参数加,或完全不加 → 映射失败
- ⚠️ 注意:如果只有一个参数(无论简单类型还是对象),
@Param可选;但若参数是对象(如User user),可直接用#{user.id},无需@Param
怎么正确写 @Param 注解
在 Mapper 接口方法的每个参数前,加上 @Param("自定义名称"),名称要和 SQL 中 #{} 里的名字严格一致(区分大小写)。
例如:
立即学习“Java免费学习笔记(深入)”;
public interface UserMapper {
// ✅ 两个字符串参数,都加 @Param
User selectByNameAndStatus(@Param("name") String name,
@Param("status") String status);
<pre class='brush:java;toolbar:false;'>// ✅ 混合类型:String + int
int updateScore(@Param("userId") Long userId,
@Param("score") int score);}
对应 XML 中写法:
<select id="selectByNameAndStatus" resultType="User">
SELECT * FROM user
WHERE name = #{name} AND status = #{status}
</select>
<p><update id="updateScore">
UPDATE user SET score = #{score} WHERE id = #{userId}
</update></p>常见错误与避坑点
-
名称拼写不一致:Java 里写
@Param("userName"),SQL 里却写#{username}→ 报错 -
误用于单个对象参数:传入
User user时加了@Param("u"),结果 SQL 得写成#{u.name};其实不加更自然,直接#{name}即可访问对象属性 -
和 @Param 混用 Map 或对象:如果方法签名是
void method(@Param("id") Long id, Map params),那#{id}和#{params.xxx}都可用,但建议统一风格,避免混乱 - IDE 提示“@Param is redundant”但实际运行报错:这是 IDE 基于静态分析误判,尤其在多模块或泛型场景下,以运行时行为为准,宁可加,别省
替代方案:用对象封装(推荐长期维护项目)
如果参数较多或语义相关,更清晰的做法是定义一个 DTO 或 Query 对象:
public class UserQuery {
private String name;
private String status;
private Integer minAge;
// getter/setter...
}
<p>// Mapper 方法
User selectByQuery(UserQuery query);</p>XML 中直接用 #{name}、#{status} —— 不需要 @Param,也更易扩展和测试。
不过对于简单双参场景(如 id + type),@Param 简洁直接,够用。


















