mybatis 动态sql(<where>和<if>)

提出问题

在查询时,经常需要动态生成sql语句,如下:

public String query(String name,Integer age,String sex){
    List list=new ArrayList();
    String sql=" select name,age,sex from user where 1=1 ";

    if(name!=null && !"".equals(name)){
        sql=sql+" and name like ?";
        list.add("%"+name+"%");
    }
    if(age!=null){
        sql=sql+" and age=?";
        list.add(age);
    }
    if(sex!=null && !"".equals(sex)){
        sql=sql+" and sex=?";
        list.add(sex);
    }
}

这种动态拼装sql的方式,非常麻烦,甚至需要有 1=1

解决问题

在mybatis中,可通过 <if> 标签解决上面的问题

<if>标签功能:

  • <if>标签中有多个条件时,要写 and 或 or ,不能写 && 或 ||

  • 拼装的sql前面一定要有 and 或 or 。当多个条件成立时,才会有 and 或 or 连接
    注意: 此时第一个 and 或 or是多余的

修改 IUserMapper

增加下面代码:

public List<User> select(User user);

修改 userMapper.xml

增加下面代码:

<select id="selectWhere" resultMap="UserMap" parameterType="top.malaoshi.entity.User" >
    select id,username,password,age,sex,status,create_time from user
    where 1=1
    <if test="username!=null and username!='' ">
        and username like #{username}
    </if>
    <if test="age!=null" >
        and age=#{age}
    </if>
    <if test="sex!=null and sex!=''">
        and sex=#{sex}
    </if>
</select>

缺点

为了符合各个查询条件,有 where 1=1 怪异的写法,不够完美

继续解决

联合使用 <where> 和 <if>

<where>标签功能:

  • 当有<if>标签成立时,会拼装条件,<where>标签才会生成 where 关键字。
    如果<if>标签没有成立的时,不会拼装条件,<where>标签不会生成 where 关键字。

  • 上面提到的, <if> 标签中,第一个 and 或 or 是多余的,<where>标签会将它们移除掉

修改 userMapper.xml

增加下面代码:

<select id="select" parameterType="org.malaoshi.entity.User" resultType="user">
    select id,username,password from user
    <where>
        <if test="username!=null and username!=''">
            and username like #{username}
        </if>
        <if test="password!=null and password!=''">
            and password=#{password}
        </if>
    </where>
</select>

测试

@Test
public void testSelect() throws IOException {

    User user=new User();
    user.setUsername("李%");
    user.setPassword("12345678");

    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    SqlSession sqlSession = sqlSessionFactory.openSession();

    IUserMapper mapper = sqlSession.getMapper(IUserMapper.class);

    List<User> list=mapper.select(user);
    for(User u:list) {
        String info = String.format("id:%s,用户名:%s,密码:%s", u.getId(), u.getUsername(), u.getPassword());
        System.out.println(info);
    }
    sqlSession.close();
    inputStream.close();
}

update语句中 <where> 和 <if>

在 update 语句中,也可以使用 <where> 和 <if> 标签,但要谨慎使用

<update id="updateById" parameterType="org.malaoshi.entity.User">
    update user set password=#{password}
    <where>
        <if test="id!=null and id!=''">
        id=#{id}
        </if>
    </where>
</update>

如果 id!=null and id!='' 为 false,那么就直接执行update user set password=#{password} ,会修改全部用户的密码

像这种情况,不要使用 <where>和<if>标签:

<update id="updateById" parameterType="org.malaoshi.entity.User">
    update user set password=#{password} where id=#{id}
</update>

原文出处:/show_1EF6ZihC0jVO.html