MyBatis(十五)——动态sql之foreach

x33g5p2x  于2021-09-24 转载在 其他  
字(6.1k)|赞(0)|评价(0)|浏览(551)
前言

mybatis的foreach标签经常用于遍历集合,构建in条件语句或者批量操作语句。

一、foreach构建in条件

foreach实现in集合或者数组是最简单常用的一种情况,语法如下:

  1. < foreach collection="集合类型" open="开始的字符" close="结束的字符"
  2. item="集合中的成员" separator="集合成员之间的分隔符">
  3. #{item 的值}
  4. </ foreach>

标签属性:
collection: 表示,循环的对象是 数组, 还是list集合。 如果dao接口方法的形参是 数组,
collection=“array” ,如果dao接口形参是List, collection=“list”。

open:循环开始时的字符。
close:循环结束时字符。
item:集合成员, 自定义的变量。
separator:集合成员之间的分隔符。
/#{item 的值}:获取集合成员的值。

1、参数是一个历 List<简单类型>

场景:通过传入的一个用户id集合来查询出所有符合条件的用户。

接口:

  1. List<Student> selectByIdList(List<Integer> idList);

mapper文件:

  1. <select id="selectByIdList" resultType="com.macay.entity.Student">
  2. select id, name, email, age from student
  3. where id in
  4. <foreach collection="list" item="ids" open="(" close=")" separator=",">
  5. #{ids}
  6. </foreach>
  7. </select>

测试类:

  1. @Test
  2. public void selectByIdList() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  5. List<Integer> list = new ArrayList<>();
  6. list.add(1);
  7. list.add(2);
  8. list.add(3);
  9. List<Student> students = mapper.selectByIdList(list);
  10. System.out.println(students);
  11. sqlSession.commit();
  12. sqlSession.close();
  13. }

结果如下:

这里一定要注意,如果入参是集合类型,mapper文件里面的collection="list"是必须的,不能想当然的写成接口入参collection=“idList”,否则会报下面的错误:

另外,假如程序中没有对集合做判空处理,前面我们这种写法还是有问题的,在集合为null或者是集合为空集合时,会有语法错误,所已为了使程序更加健壮,我们还需要加上判空操作,mapper代码如下:

  1. <select id="selectByIdList" resultType="com.macay.entity.Student">
  2. select id, name, email, age from student
  3. <if test="list !=null and list.size > 0">
  4. where id in
  5. <foreach collection="list" item="ids" open="(" close=")" separator=",">
  6. #{ids}
  7. </foreach>
  8. </if>
  9. </select>

可以看到,即使集合为空,也不会有语法错误。

2、参数是一个 List<对象类型>

接口:

  1. List<Student> selectByIdList2(List<Student> students);

mapper文件:

  1. <select id="selectByIdList2" resultType="com.macay.entity.Student">
  2. select id, name, email, age from student
  3. <if test="list !=null and list.size > 0">
  4. where id in
  5. <foreach collection="list" item="stu" open="(" close=")" separator=",">
  6. #{stu.id}
  7. </foreach>
  8. </if>
  9. </select>

注意:如果list里面是对象类型,在引用的时候使用的是”属性.属性“的方式,如stu.id。

测试类:

  1. @Test
  2. public void selectByIdList2() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  5. List<Student> list = new ArrayList<>();
  6. Student student = new Student();
  7. student.setId(1);
  8. Student student1 = new Student();
  9. student1.setId(2);
  10. list.add(student);
  11. list.add(student1);
  12. List<Student> students = mapper.selectByIdList2(list);
  13. System.out.println(students);
  14. sqlSession.commit();
  15. sqlSession.close();
  16. }

结果如下:

3、参数是一个数组类型

接口:

  1. List<Student> selectByIdArray(Integer[] idArray);

mapper文件:

  1. <select id="selectByIdArray" resultType="com.macay.entity.Student">
  2. select id, name, email, age from student
  3. where id in
  4. <foreach collection="array" item="ids" open="(" close=")" separator=",">
  5. #{ids}
  6. </foreach>
  7. </select>

加上数组判空的处理:

  1. <select id="selectByIdArray" resultType="com.macay.entity.Student">
  2. select id, name, email, age from student
  3. <if test="array !=null">
  4. where id in
  5. <foreach collection="array" item="ids" open="(" close=")" separator=",">
  6. #{ids}
  7. </foreach>
  8. </if>
  9. </select>

测试类:

  1. @Test
  2. public void selectByIdArray() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  5. List<Integer> list = new ArrayList<>();
  6. Integer[] ids = new Integer[3];
  7. list.add(1);
  8. list.add(2);
  9. list.add(3);
  10. Integer[] integers = list.toArray(ids);
  11. List<Student> students = mapper.selectByIdArray(integers);
  12. System.out.println(students);
  13. sqlSession.commit();
  14. sqlSession.close();
  15. }

结果如下:

二、foreach用于批量操作
1、foreach实现批量插入

在mysql中,批量插入的语法如下:

  1. insert into table_name (c1, c2, c3 ...) values (v1a, v2a, v3a), (v1b, v2b, v3b),(v1c, v2c, v3c)....

从待处理的部分可以看到,后面的值是一个循环体,因此可以通过foreach实现循环插入。

接口:

  1. int insertStudentBatch(List<Student> students);

mapper文件:

  1. <insert id="insertStudentBatch">
  2. insert into student (id, name, email, age)
  3. values
  4. <foreach collection="list" separator="," item="stu">
  5. (#{stu.id}, #{stu.name}, #{stu.email}, #{stu.age})
  6. </foreach>
  7. </insert>

测试类:

  1. @Test
  2. public void insertStudentBatch() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  5. List<Student> list = new ArrayList<>();
  6. Student student = new Student();
  7. student.setId(22);
  8. student.setName("test20");
  9. student.setAge(20);
  10. student.setEmail("test20@qq.com");
  11. Student student1 = new Student();
  12. student1.setId(23);
  13. student1.setName("test21");
  14. student1.setAge(21);
  15. student1.setEmail("test21@qq.com");
  16. list.add(student);
  17. list.add(student1);
  18. if (CollectionUtils.isNotEmpty(list)) {
  19. int count = mapper.insertStudentBatch(list);
  20. System.out.println(count);
  21. }
  22. sqlSession.commit();
  23. sqlSession.close();
  24. }
2、foreach实现动态update

这里主要介绍,当参数是map时,foreach如何实现动态update。

当参数是Map类型的时候,foreach标签的index属性值对应的不是索引值,而是Map中的key,利用这个key可以实现动态update。

接口:

  1. int updateStudentByMap(Map<String, Object> map);

mapper文件:

  1. <update id="updateStudentByMap" >
  2. update student set
  3. <foreach collection="_parameter" item="val" index="key" separator=",">
  4. ${key} = #{val}
  5. </foreach>
  6. where id = #{id}
  7. </update>

注意,这里可以通过@param注解来指定参数名,也可以使用mybatis内部默认的_parameter作为该参数的key,所有XML中也使用了_parameter。

测试类:

  1. @Test
  2. public void updateStudentByMap() {
  3. SqlSession sqlSession = SqlSessionUtils.getSqlSession();
  4. StudentDao mapper = sqlSession.getMapper(StudentDao.class);
  5. Map<String, Object> map = new HashMap<>();
  6. map.put("id", 3);
  7. map.put("name", "test3");
  8. map.put("email", "test3@qq.com");
  9. if (MapUtils.isNotEmpty(map)) {
  10. int count = mapper.updateStudentByMap(map);
  11. System.out.println(count);
  12. }
  13. System.out.println(mapper.selectById(3));
  14. sqlSession.commit();
  15. sqlSession.close();
  16. }

结果如下:

相关文章