学科分类
目录
SSM框架

<foreach>元素

在实际开发中,有时可能会遇到这种的情况:假设在一个客户表中有1000条数据,现在需要将id值小于100的客户信息全部查询出来,这要怎么做呢?有人也许会说,“我可以一条一条查出来”,那如果查询200、300甚至更多也一条一条查么?这显然是不可取的。有的人会想到,可以在Java方法中使用循环,将查询方法放在循环语句中,然后通过条件循环的方式查询出所需的数据。这种查询方式虽然可行,但每执行一次循环语句,都需要向数据库中发送一条查询SQL,其查询效率是非常低的。那么还有其他更好的方法么?我们能不能通过SQL语句来执行这种查询呢?

其实,MyBatis中已经提供了一种用于数组和集合循环遍历的方式,那就是使用<foreach>元素,我们完全可以通过<foreach>元素来解决上述类似的问题。

<foreach>元素通常在构建IN条件语句时使用。其使用方式如下:

<!--<foreach>元素使用 -->
<select id="findCustomerByIds" parameterType="List"
         resultType="com.itheima.po.Customer">
    select * from t_customer where id in
    <foreach item="id" index="index" collection="list" 
               open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

在上述代码中,使用了<foreach>元素对传入的集合进行遍历并进行了动态SQL组装。关于<foreach>元素中使用的几种属性的描述具体如下:

● item:配置的是循环中当前的元素。

● index:配置的是当前元素在集合的位置下标。

● collection:配置的list是传递过来的参数类型(首字母小写),它可以是一个array、list(或collection)、Map集合的键、POJO包装类中数组或集合类型的属性名等。

● open和close:配置的是以什么符号将这些集合元素包装起来。

● separator:配置的是各个元素的间隔符。

注意:

你可以将任何可迭代对象(如列表、集合等)和任何的字典或者数组对象传递给<foreach>作为集合参数。当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。

为了验证上述配置,可以在测试类MybatisTest中,编写测试方法findCustomerByIdsTest(),其代码如下所示。

/**
 * 根据客户编号批量查询客户信息
 */
@Test
public void findCustomerByIdsTest(){
    // 获取SqlSession
    SqlSession session = MybatisUtils.getSession();
    // 创建List集合,封装查询id
    List<Integer> ids=new ArrayList<Integer>();
    ids.add(1);
    ids.add(2);
    // 执行SqlSession的查询方法,返回结果集
    List<Customer> customers = session.selectList("com.itheima.mapper"
            + ".CustomerMapper.findCustomerByIds", ids);
    // 输出查询结果信息    
    for (Customer customer : customers) {
        // 打印输出结果
        System.out.println(customer);
    }
    // 关闭SqlSession
    session.close();
}

在上述代码中,执行查询操作时传入了一个客户编号集合ids。

使用JUnit4执行findCustomerByIdsTest()方法后,控制台的输出结果如图1所示。

图1 运行结果

从图1可以看出,使用<foreach>元素已对传入的客户编号集合进行了动态SQL组装,最终成功批量查询出了对应的客户信息。

脚下留心:collection属性

在使用<foreach>时最关键也是最容易出错的就是collection属性,该属性是必须指定的,而且在不同情况下,该属性的值是不一样的。主要有以下3种情况:

  1. 如果传入的是单参数且参数类型是一个数组或者List的时候,collection属性值分别为array和list(或collection);

  2. 如果传入的参数是多个的时候,就需要把它们封装成一个Map了,当然单参数也可以封装成Map集合,这时候collection属性值就为Map的键。

  3. 如果传入的参数是POJO包装类的时候,collection属性值就为该包装类中需要进行遍历的数组或集合的属性名。

所以在设置collection属性值的时候,必须按照实际情况配置,否则程序就会出现异常。 例如,将上述<foreach>元素中collection的属性值设置为array,则程序执行后,将出现如图2所示的异常。

图2 运行结果

点击此处
隐藏目录