How to properly use the @Param annotation of Mybatis

烂漫一生 提交于 2020-05-14 09:23:05

问题


I didn't use @Param annotation at first, this is my mapper.java

public void changeUserAuth(Integer userId,int identity);

, and this is my 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>

then it works correctly!I continue to write like this, as follows:

//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>

however,it gave an error,the message is

There is no getter for property named 'userId' in 'class.java.lang.Integer'

I can understand that mybatis cannot parse the Integer, but why it is not an error like my first use, just because I have an int type Parameter? In the second method, I have to use @Param annotation


回答1:


Here is how you reference parameters in MyBatis statements.

I'll use this POJO in the following explanation.

public class User {
  private Integer id;
  private String name;
  //...
}

When @Param is used

If you add @Param annotation on a parameter, you can use the specified name to reference the parameter. This is the simplest case.

A few examples:

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

void insert(@Param("record") User user);
<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>

Without @Param

If there is no @Param, it depends on several conditions.

When the mapper method takes only one parameter [1] and ...

  1. ... the sole parameter is assignable to java.util.List, you can reference the parameter as list.

    List<User> selectByIds(List<Integer> ids);
    
    <select id="select" resultType="User">
      select * from users
      where id in (
        <foreach item="x" collection="list" separator=",">
          #{x}
        </foreach>
      )
    </select>
    
  2. ... the sole parameter is assignable to java.util.Collection, you can reference the parameter as collection.

    List<User> selectByIds(Set<Integer> ids);
    
    <select id="select" resultType="User">
      select * from users
      where id in (
        <foreach item="x" collection="collection" separator=",">
          #{x}
        </foreach>
      )
    </select>
    
  3. ... there is a type handler mapped to the sole parameter (i.e. the parameter is String, Integer, etc.).

    • With MyBatis 3.5.2 and later, you can reference the parameter using any name (you should use sensible names for obvious reasons, though). e.g.

      List<User> select(Integer id);
      
      <select id="select" resultType="User">
        select * from users
        <where>
          <if test="x != null">and id = #{y}</if>
        </where>
      </select>
      
    • With MyBatis 3.5.1

      • you can reference the parameter with any name in #{}.
      • you must reference the parameter as _parameter in ${}, test attribute of <if /> and <when /> and value attribute of <bind />. This is why your second example throws exception.

      List<User> select(Integer id);
      
      <select id="select" resultType="User">
        select * from users
        <where>
          <if test="_parameter != null">and id = #{z}</if>
        </where>
      </select>
      
  4. ... there is no type handler mapped to the sole parameter (i.e. the parameter is POJO or Map<String, ?>), you can reference the parameter properties directly with their names (or the keys if the parameter is a Map).

    void insert(User user);
    
    <insert id="insert">
      insert into users (id, name) values
        (#{id}, #{name})
    </insert>
    

When the mapper method takes multiple parameters

  1. If the project is compiled with '-parameters' compiler option, you can reference the parameters using their names declared in the method signature. This is your first example.

    List<USer> select(Integer userId, String userName);
    
    <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>
    
  2. Otherwise, you can reference the parameters using the names implicitly assigned by MyBatis i.e. arg0, arg1, ... (I would not recommend this as it's fragile and error-prone).

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

[1] RowBounds and ResultHandler does not count.



来源:https://stackoverflow.com/questions/59668117/how-to-properly-use-the-param-annotation-of-mybatis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!