choose用法

上一节的 if 标签提供了基本的条件判断,但是它无法实现 if…​else、if…​else…​ 的逻辑,要想实现这样的逻辑,就需要用到 choose when otherwise 标签。choose 元素中包含 when 和 otherwise 两个标签,一个 choose 中至少有一个 when,有 0 个或者 1 个 otherwise。在已有的 sys_user 表中,除了主键 id 外,我们认为 user_name(用户名)也是唯一的,所有的用户名都不可以重复。现在进行如下查询:当参数 id 有值的时候优先使用 id 查询,当 id 没有值时就去判断用户名是否有值,如果有值就用用户名查询,如果用户名也没有值,就使 SQL 查询无结果。

首先在 UserMapper 中添加如下接口。

/**
 * 根据用户ID或用户名查询
 * @param sysUser 用户
 * @return 用户信息
 */
SysUser selectByIdOrUserName(SysUser sysUser);

然后在 UserMapper.xml 中添加如下 SQL。

<select id="selectByIdOrUserName" resultMap="baseResultMap">
    select id,
        user_name userName,
        user_password userPassword,
        user_email userEmail,
        user_info userInfo,
        head_img headImg,
        create_time createTime
    from sys_user
    where 1=1
    <choose>
        <when test="id != null">
            and id = #{id}
        </when>
        <when test="userName != null and userName != ''">
            and user_name = #{userName}
        </when>
        <otherwise>
            and 1 = 2
        </otherwise>
    </choose>
</select>

使用 choose when otherwise 的时候逻辑要严密,避免由于某些值出现问题导致 SQL 出错。

在以上查询中,如果没有 otherwise 这个限制条件,所有的用户都会被查询出来,因为我们在对应的接口方法中使用了 SysUser 作为返回值,所以当实际查询结果是多个时就会报错。添加 otherwise 条件后,由于 where 条件不满足,因此在这种情况下就查询不到结果。

针对这个方法,编写如下测试。

@Test
public void testSelectByIdOrUserName(){
    SqlSession sqlSession = getSqlSession();
    try {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 只查询用户名时
        SysUser query = new SysUser();
        query.setId(1L);
        query.setUserName("admin");
        SysUser user = userMapper.selectByIdOrUserName(query);
        Assert.assertNotNull(user);
        // 当没有id时
        query.setId(null);
        user = userMapper.selectByIdOrUserName(query);
        Assert.assertNotNull(user);
        // 当id和name都为空时
        query.setUserName(null);
        user = userMapper.selectByIdOrUserName(query);
        Assert.assertNull(user);
    } finally {
        // 不要忘记关闭 sqlSession
        sqlSession.close();
    }
}

测试输出日志如下。

choose 用法并不复杂,通过这个例子以及 if 中的多个例子,相信大家应该很容易掌握 choose 的用法。