MyBatis系列(六):MyBatis动态Sql之if标签的用法

本篇博客主要讲解如何使用if标签生成动态的Sql,主要包含以下3个场景:

  1. 根据查询条件实现动态查询
  2. 根据参数值实现动态更新某些列
  3. 根据参数值实现动态插入某些列

1. 使用if标签实现动态查询

假设有这样1个需求:根据用户的输入条件来查询用户列表,如果输入了用户名,就根据用户名模糊查询,如果输入了邮箱,就根据邮箱精确查询,如果同时输入了用户名和邮箱,就用这两个条件去匹配用户。

首先,我们在接口SysUserMapper中添加如下方法:

/**
 * 根据动态条件查询用户信息
 *
 * @param sysUser
 * @return
 */
List<SysUser> selectByUser(SysUser sysUser);

然后在对应的SysUserMapper.xml中添加如下代码:

<select id="selectByUser" resultType="com.zwwhnly.mybatisaction.model.SysUser">
    SELECT  id,
            user_name,
            user_password,
            user_email,
            create_time
    FROM sys_user
    WHERE 1 = 1
    <if test="userName != null and userName != ''">
        AND user_name LIKE CONCAT('%',#{userName},'%')
    </if>
    <if test="userEmail != null and userEmail != ''">
        AND user_email = #{userEmail}
    </if>
</select>

代码简单讲解:

1)if标签的test属性必填,该属性值是一个符合OGNL要求的判断表达式,一般只用true或false作为结果。

2)判断条件property != null 或 property == null,适用于任何类型的字段,用于判断属性值是否为空。

3)判断条件property != ‘’ 或 property == ‘’,仅适用于String类型的字段,用于判断是否为空字符串。

4)当有多个判断条件时,使用and或or进行连接,嵌套的判断可以使用小括号分组,and相当于Java中的与(&&),or相关于Java中的或(||)。

所以上面代码的意思就是先判断字段是否为null,然后再判断字段是否为空字符串。

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Test
public void testSelectByUser() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        // 只按用户名查询
        SysUser query = new SysUser();
        query.setUserName("ad");
        List<SysUser> sysUserList = sysUserMapper.selectByUser(query);
        Assert.assertTrue(sysUserList.size() > 0);

        // 只按邮箱查询
        query = new SysUser();
        query.setUserEmail("test@mybatis.tk");
        sysUserList = sysUserMapper.selectByUser(query);
        Assert.assertTrue(sysUserList.size() > 0);

        // 同时按用户民和邮箱查询
        query = new SysUser();
        query.setUserName("ad");
        query.setUserEmail("test@mybatis.tk");
        sysUserList = sysUserMapper.selectByUser(query);
        // 由于没有同时符合这两个条件的用户,因此查询结果数为0
        Assert.assertTrue(sysUserList.size() == 0);
    } finally {
        sqlSession.close();
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_name LIKE CONCAT(’%’,?,’%’)

DEBUG [main] - ==> Parameters: ad(String)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_email = ?

DEBUG [main] - ==> Parameters: test@mybatis.tk(String)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_name LIKE CONCAT(’%’,?,’%’) AND user_email = ?

DEBUG [main] - ==> Parameters: ad(String), test@mybatis.tk(String)

DEBUG [main] - <== Total: 0

2. 使用if标签实现动态更新

假设有这样1个需求:更新用户信息的时候不能将原来有值但没有发生变化的字段更新为空或null,即只更新有值的字段。

首先,我们在接口SysUserMapper中添加如下方法:

/**
 * 根据主键选择性更新用户信息
 *
 * @param sysUser
 * @return
 */
int updateByIdSelective(SysUser sysUser);

然后在对应的SysUserMapper.xml中添加如下代码:

<update id="updateByIdSelective">
    UPDATE sys_user
    SET
    <if test="userName != null and userName != ''">
        user_name = #{userName},
    </if>
    <if test="userPassword != null and userPassword != ''">
        user_password = #{userPassword},
    </if>
    <if test="userEmail != null and userEmail != ''">
        user_email = #{userEmail},
    </if>
    <if test="userInfo != null and userInfo != ''">
        user_info = #{userInfo},
    </if>
    <if test="headImg != null">
        head_img = #{headImg,jdbcType=BLOB},
    </if>
    <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
    </if>
    id = #{id}
    WHERE id = #{id}
</update>

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Test
public void testUpdateByIdSelective() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        SysUser sysUser = new SysUser();
        // 更新id=1的用户
        sysUser.setId(1L);
        // 修改邮箱
        sysUser.setUserEmail("test@mybatis.tk");

        int result = sysUserMapper.updateByIdSelective(sysUser);
        Assert.assertEquals(1, result);

        // 查询id=1的用户
        sysUser = sysUserMapper.selectById(1L);
        // 修改后的名字保持不变,但是邮箱变成了新的
        Assert.assertEquals("admin", sysUser.getUserName());
        Assert.assertEquals("test@mybatis.tk", sysUser.getUserEmail());
    } finally {
        sqlSession.close();
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: UPDATE sys_user SET user_email = ?, id = ? WHERE id = ?

DEBUG [main] - ==> Parameters: test@mybatis.tk(String), 1(Long), 1(Long)

DEBUG [main] - <== Updates: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE id = ?

DEBUG [main] - ==> Parameters: 1(Long)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1, admin, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

3. 使用if标签实现动态插入

假设有这样1个需求:往数据库表中插入数据的时候,如果某一列的参数值不为空,就使用传入的值,如果传入的参数值为空,就使用数据库中的默认值(通常是空),而不使用传入的空值。

为了更好的理解该示例,我们先给sys_user表的user_email字段设置默认值:test@mybatis.tk,Sql语句如下:

ALTER TABLE sys_user
MODIFY COLUMN user_email VARCHAR(50) NULL DEFAULT  'test@mybatis.tk'
COMMENT '邮箱'
AFTER user_password;

首先,我们在接口SysUserMapper中添加如下方法:

/**
 * 根据传入的参数值动态插入列
 *
 * @param sysUser
 * @return
 */
int insertSelective(SysUser sysUser);

然后在对应的SysUserMapper.xml中添加如下代码:

<insert id="insertSelective" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO sys_user(user_name, user_password,
    <if test="userEmail != null and userEmail != ''">
        user_email,
    </if>
    user_info, head_img, create_time)
    VALUES (#{userName},#{userPassword},
    <if test="userEmail != null and userEmail != ''">
        #{userEmail},
    </if>
    #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})
</insert>

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Test
public void testInsertSelective() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        SysUser sysUser = new SysUser();
        sysUser.setUserName("test-selective");
        sysUser.setUserPassword("123456");
        sysUser.setUserInfo("test info");
        sysUser.setCreateTime(new Date());

        sysUserMapper.insertSelective(sysUser);

        // 获取刚刚插入的数据
        sysUser = sysUserMapper.selectById(sysUser.getId());
        // 因为没有指定userEmail,所以用的是数据库的默认值
        Assert.assertEquals("test@mybatis.tk", sysUser.getUserEmail());
    } finally {
        sqlSession.close();
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: INSERT INTO sys_user(user_name, user_password, user_info, head_img, create_time) VALUES (?,?, ?,?,?)

DEBUG [main] - ==> Parameters: test-selective(String), 123456(String), test info(String), null, 2019-07-08 11:40:36.927(Timestamp)

DEBUG [main] - <== Updates: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE id = ?

DEBUG [main] - ==> Parameters: 1021(Long)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1021, test-selective, 123456, test@mybatis.tk, 2019-07-08 11:40:37.0

DEBUG [main] - <== Total: 1

4. 源码及参考

源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。

刘增辉《MyBatis从入门到精通》

原创不易,如果觉得文章能学到东西的话,欢迎点个赞、评个论、关个注,这是我坚持写作的最大动力。

如果有兴趣,欢迎添加我的微信:zwwhnly,等你来聊技术、职场、工作等话题(PS:我是一名奋斗在上海的程序员)。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: MyBatis是一个流行的ORM框架,通过Mapper文件将Java对象映射到SQL语句。MyBatis的Mapper文件是一个XML文件,它包含了可以执行的SQL语句。动态SQLMyBatis的一个重要的功能,可以根据不同情况,生成不同的SQL语句,从而实现更加灵活的查询。 if标签MyBatis动态SQL的一种标签,它可以根据条件生成动态SQL语句。if标签的语法如下: ``` <if test="condition1"> SQL语句 </if> ``` 其中,test属性表示需要判断的条件,可以是一个字符串表达式或者OGNL表达式。SQL语句则是当满足条件时需要执行的SQL语句。如果条件不满足,则不会执行这段SQL语句。 if标签可以包含多个嵌套的if标签,以实现更加复杂的条件判断。同时,还可以使用choose、when、otherwise标签结合if标签,实现更加灵活的条件判断。例如: ``` <select id="queryUsers" resultType="User"> SELECT * FROM users <where> <if test="username != null and username != ''"> AND username LIKE '%${username}%' </if> <if test="gender != null and gender != ''"> AND gender = #{gender} </if> <choose> <when test="orderBy == 'name'"> ORDER BY username </when> <when test="orderBy == 'age'"> ORDER BY age </when> <otherwise> ORDER BY id </otherwise> </choose> </where> </select> ``` 以上例子是一个查询用户的SQL语句,根据不同情况生成不同的SQL语句。其中,if标签根据传入的参数判断是否需要加入username、gender的查询条件,choose标签根据orderBy的值,生成不同的排序条件。 if标签MyBatis动态SQL的重要功能之一,可以根据条件生成不同的SQL语句,从而实现更加灵活的查询。熟练掌握if标签的使用,可以使MyBatis开发更加高效和灵活。 ### 回答2: Mybatis是一款流行的Java ORM框架,它提供了许多方便的功能,其中之一就是动态SQL。当我们需要根据不同的条件拼接SQL语句时,就可以使用动态SQL来实现。具体来说,if标签是其中一种实现方式,下面将详解其用法。 if标签可以用于where、set、foreach等标签中,用于判断当前条件是否成立,如果成立就拼接相应的SQL语句,否则不进行任何操作。其基本语法如下: <if test="condition"> SQL语句 </if> 其中,test属性用于指定判断条件,可以是简单的表达式或者是复杂的逻辑语句。下面是一些常用的判断条件: 1. 判断参数是否为空 <if test="param != null"> SQL语句 </if> 2. 判断字符串是否为空 <if test="str != ''"> SQL语句 </if> 3. 判断是否相等 <if test="param == 'value'"> SQL语句 </if> 4. 判断是否大于 <if test="param > 10"> SQL语句 </if> 5. 判断是否包含 <if test="str.indexOf('value') != -1"> SQL语句 </if> 除了以上几种基本用法,if标签还可以嵌套使用,用于实现更复杂的判断逻辑。例如: <if test="param1 != null"> SQL语句 <if test="param2 != null"> SQL语句 </if> </if> 上述代码示例中,如果param1不为空,就会拼接第一个SQL语句;如果param2也不为空,则会在第一个SQL语句之后再拼接第二个SQL语句。 总的来说,if标签Mybatis动态SQL的基础,能够帮助我们实现更加灵活的SQL拼接,提高代码的可读性和可维护性。学习和掌握其使用方法,对于开发高效、高质量的程序是非常有帮助的。 ### 回答3: MyBatis是一款非常优秀的Java持久层框架,提供了丰富的SQL查询方式。在进行SQL查询的时候,经常需要根据具体的条件组合而成不同的SQL语句。这个时候可以使用MyBatis动态SQL特性。在动态SQL中,if标签是常用的一种方式。下面就来详解一下if标签用法。 if标签的作用:在SQL语句中根据判断条件动态生成SQL语句。相当于Java中的if语句。 if标签用法:在Mapper.xml文件中,使用if标签包裹需要动态生成的SQL。if标签的属性为test,表示判断条件。属性值可以是任何符合OGNL规则的表达式,常见的有以下几种方式: 1. 如果条件不为空,则生成相应的SQL语句:<![CDATA[需要动态生成的SQL语句]]>。 例如: <select id="findUser" parameterType="User" resultMap="UserMap"> SELECT * FROM user <where> <if test="name != null and name != ''"> AND name = #{name} </if> </where> </select> 当调用findUser方法时,如果传入的name不为空,那么就会生成如下的SQL语句: SELECT * FROM user WHERE name = ? 2. 如果条件为true,则生成相应的SQL语句: 例如: <select id="findUsers" resultMap="UserMap"> SELECT * FROM user <where> <if test="name != null and name != ''"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select> 当调用findUsers方法时,如果传入的name和age分别为"Tom"和20,那么就会生成如下的SQL语句: SELECT * FROM user WHERE name = 'Tom' AND age = 20 3. 如果条件为false,则不在生成相应的SQL语句: 例如: <select id="findUsers" resultMap="UserMap"> SELECT * FROM user <where> <if test="name != null and name != ''"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select> 当调用findUsers方法时,如果传入的name为"Tom",age为空,那么就会生成如下的SQL语句: SELECT * FROM user WHERE name = 'Tom' if标签的嵌套: if标签可以进行嵌套,从而实现更加灵活的SQL生成方式。 例如: <select id="findUsers" resultMap="UserMap"> SELECT * FROM user <where> <if test="name != null and name != ''"> AND name = #{name} </if> <if test="age != null"> <if test="age < 18"> AND age < 18 </if> <if test="age >= 18 and age < 30"> AND age >= 18 AND age < 30 </if> <if test="age >= 30"> AND age >= 30 </if> </if> </where> </select> 当调用findUsers方法时,如果传入的name为空,age为25,那么就会生成如下的SQL语句: SELECT * FROM user WHERE age >= 18 AND age < 30 以上就是if标签用法详解。使用if标签可以让查询条件更加灵活、动态,深受开发者们的喜爱。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值