跳转至

MyBatis 如何获取接口参数名?

一、背景

Mapper 接口:

User selectBy(String name, Integer age);

XML:

<select id="selectBy" resultType="User">
    SELECT * FROM user WHERE name = #{name} AND age = #{age}
</select>

为什么有的项目 #{name} 能用,有的项目必须写 #{arg0}

二、ParamNameResolver 的工作

MyBatis 用 ParamNameResolver 解析参数。它的判断逻辑:

  1. 方法参数有 @Param:用注解的 value 作为 key。
  2. 没有 @Param,且编译保留了参数名-parameters 或 LocalVariableTable):用真实参数名。
  3. 都没有:用 arg0, arg1, ...param1, param2, ...

三、为什么 IDE 里好用、打 jar 后报错

  • IDE(IDEA/Eclipse)默认编译带调试信息 -g,LocalVariableTable 里有真实参数名,MyBatis 3.4.1+ 可以读出来。
  • Maven 默认 maven-compiler-plugin 不一定带 -parameters,打出来的 jar 就拿不到。

四、解决方案

方案 1:加 @Param(最稳)

User selectBy(@Param("name") String name, @Param("age") Integer age);

方案 2:编译加 -parameters(JDK 8+)

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <parameters>true</parameters>
    </configuration>
</plugin>

方案 3:MyBatis 配置

mybatis.configuration.use-actual-parameter-name=true

这个配置默认就是 true,但前提是 class 文件里真有参数名。

五、多参数默认命名规则

即使什么都不加,MyBatis 也会按以下方式命名:

// 两个参数 args[0], args[1]
#{arg0}  #{param1}
#{arg1}  #{param2}

arg0/arg1 在新版 MyBatis 中可能需要开 -parameters 才能用,param1/param2 永远可用。

六、单个参数的特殊情况

如果方法只有一个参数且没有 @Param,XML 中 #{xxx} 可以写任意名字(MyBatis 不校验):

User selectById(Long id);

<select id="selectById">
    SELECT * FROM user WHERE id = #{whatever}
</select>

这是因为单参数不需要 key。

生产建议

团队规范:多参数一律加 @Param,避免"IDE 能跑、线上报错"的坑。