<choose>、<when>、<otherwise>元素
在使用<if>元素时,只要test属性中的表达式为true,就会执行元素中的条件语句,但是在实际应用中,有时只需要从多个选项中选择一个去执行。
例如下面的场景:
“当客户名称不为空,则只根据客户名称进行客户筛选;
当客户名称为空,而客户职业不为空,则只根据客户职业进行客户筛选。
当客户名称和客户职业都为空,则要求查询出所有电话不为空的客户信息。”
此种情况下,使用<if>元素进行处理是非常不合适的。如果使用的是Java语言,这种情况显然更适合使用switch…case…default语句来处理。那么在MyBatis中有没有类似的语句呢?答案是肯定的。针对上面情况,MyBatis中可以使用<choose>、<when>、<otherwise>元素进行处理。下面让我们看看如何使用<choose>、<when>、<otherwise>元素组合去实现上面的情况。
(1)在映射文件CustomerMapper.xml中,使用<choose>、<when>、<otherwise>元素执行上述情况的动态SQL代码如下所示。
<!--<choose>(<when>、<otherwise>)元素使用 -->
<select id="findCustomerByNameOrJobs"
parameterType="com.itheima.po.Customer"
resultType="com.itheima.po.Customer">
select * from t_customer where 1=1
<choose>
<when test="username !=null and username !=''">
and username like concat('%',#{username}, '%')
</when>
<when test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>
在上述代码中,使用了<choose>元素进行SQL拼接,当第一个<when>元素中的条件为真,则只动态组装第一个<when>元素内的SQL片段,否则就继续向下判断第二个<when>元素中的条件是否为真,以此类推。当前面所有when元素中的条件都不为真时,则只组装<otherwise>元素内的SQL片段。
(2)在测试类MybatisTest中,编写测试方法findCustomerByNameOrJobsTest(),其代码如下所示。
/**
* 根据客户姓名或职业查询客户信息列表
*/
@Test
public void findCustomerByNameOrJobsTest(){
// 通过工具类生成SqlSession对象
SqlSession session = MybatisUtils.getSession();
// 创建Customer对象,封装需要组合查询的条件
Customer customer = new Customer();
customer.setUsername("jack");
customer.setJobs("teacher");
// 执行SqlSession的查询方法,返回结果集
List<Customer> customers = session.selectList("com.itheima.mapper"
+ ".CustomerMapper.findCustomerByNameOrJobs",customer);
// 输出查询结果信息
for (Customer customer2 : customers) {
// 打印输出结果
System.out.println(customer2);
}
// 关闭SqlSession
session.close();
}
使用JUnit4执行findCustomerByNameOrJobsTest()方法后,控制台的输出结果如图1所示。
图1 运行结果
从图1可以看出,虽然同时传入了姓名和职业两个查询条件,但MyBatis所生成的SQL只是动态组装了客户姓名进行条件查询。
如果将上述代码中“customer.setUsername("jack");”删除或者注释掉,然后再次执行findCustomerByNameOrJobsTest()方法时,控制台的输出结果如图2所示。
图2 运行结果
从图2可以看出,MyBatis生成的SQL组装了客户职业进行条件查询,同样查询出了客户信息。
如果将设置客户姓名和职业参数值的两行代码都注释(即客户姓名和职业都为空),那么程序的执行结果如图3所示。
图3 运行结果
从图3可以看出,当姓名和职业参数都为空时,MyBatis的SQL组装了<otherwise>元素中的SQL片段进行条件查询。