如何正确使用Mybatis的@Param注解

A s*_*ams 1 annotations mybatis

一开始我没有使用@Param注解,这是我的mapper.java

public void changeUserAuth(Integer userId,int identity);
Run Code Online (Sandbox Code Playgroud)

,这是我的 mapper.xml

<update id="changeUserAuth">
    update user
    <set>
        <if test="identity != 0">identity = #{identity}</if>
    </set>
    <where>
        <if test="userId != 0">userId = #{userId}</if>
    </where>
</update>
Run Code Online (Sandbox Code Playgroud)

那么就正常运行了!我继续这样写,如下:

//this's mapper.java
public void updateUserStatus(Integer userId);

<!--this is mapper.xml>
<update id="changeUserAuth">
    update user
    set deleteFlag= true
    <where>
        <if test="userId != 0">userId = #{userId}</if>
    </where>
</update>
Run Code Online (Sandbox Code Playgroud)

然而,它给出了一个错误,消息是

'class.java.lang.Integer' 中没有名为 'userId' 的属性的 getter

我可以理解mybatis无法解析Integer,但是为什么它不像我第一次使用那样错误,仅仅因为我有一个int类型的参数?在第二种方法中,我必须使用@Param注解

ave*_*ave 8

以下是在 MyBatis 语句中引用参数的方式。

我将在下面的解释中使用这个 POJO。

public class User {
  private Integer id;
  private String name;
  //...
}
Run Code Online (Sandbox Code Playgroud)

什么时候@Param使用

如果@Param在参数上添加注释,则可以使用指定的名称来引用该参数。这是最简单的情况。

几个例子:

List<USer> select(@Param("id") Integer userId, @Param("name") String userName);

void insert(@Param("record") User user);
Run Code Online (Sandbox Code Playgroud)
<select id="select" resultType="User">
  select * from users
  <where>
    <if test="id != null">and id = #{id}</if>
    <if test="name != null">and name = #{name}</if>
  </where>
</select>

<insert id="insert">
  insert into users (id, name) values
    (#{record.id}, #{record.name})
</insert>
Run Code Online (Sandbox Code Playgroud)

没有 @Param

如果没有@Param,则取决于几个条件。

当 mapper 方法只接受一个参数 [1] 和 ...

  1. ...唯一的参数可分配给java.util.List,您可以将该参数引用为list

    List<User> selectByIds(List<Integer> ids);
    
    Run Code Online (Sandbox Code Playgroud)
    <select id="select" resultType="User">
      select * from users
      where id in (
        <foreach item="x" collection="list" separator=",">
          #{x}
        </foreach>
      )
    </select>
    
    Run Code Online (Sandbox Code Playgroud)
  2. ...唯一的参数可分配给java.util.Collection,您可以将该参数引用为collection

    List<User> selectByIds(Set<Integer> ids);
    
    Run Code Online (Sandbox Code Playgroud)
    <select id="select" resultType="User">
      select * from users
      where id in (
        <foreach item="x" collection="collection" separator=",">
          #{x}
        </foreach>
      )
    </select>
    
    Run Code Online (Sandbox Code Playgroud)
  3. ...有映射到唯一的参数类型的处理程序(即该参数StringInteger等)。

  4. ...没有映射到唯一参数的类型处理程序(即参数是 POJO 或Map<String, ?>),您可以直接使用它们的名称(如果参数是 a 则使用键)引用参数属性Map

    <select id="select" resultType="User">
      select * from users
      <where>
        <if test="_parameter != null">and id = #{z}</if>
      </where>
    </select>
    
    Run Code Online (Sandbox Code Playgroud)
    void insert(User user);
    
    Run Code Online (Sandbox Code Playgroud)

当 mapper 方法接受多个参数时

  1. 如果项目是使用“-parameters”编译器选项编译的,您可以使用在方法签名中声明的名称来引用参数。这是你的第一个例子。

    <insert id="insert">
      insert into users (id, name) values
        (#{id}, #{name})
    </insert>
    
    Run Code Online (Sandbox Code Playgroud)
    List<USer> select(Integer userId, String userName);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 否则,您可以使用 MyBatis 隐式分配的名称来引用参数,即arg0, arg1, ... (我不建议这样做,因为它很脆弱且容易出错)。

    <select id="select" resultType="User">
      select * from users
      <where>
        <if test="id != null">and id = #{id}</if>
        <if test="name != null">and name = #{name}</if>
      </where>
    </select>
    
    Run Code Online (Sandbox Code Playgroud)
    List<USer> select(Integer userId, String userName);
    
    Run Code Online (Sandbox Code Playgroud)

[1]RowBoundsResultHandler不算数。