Mybatis最入门---动态查询(foreach)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

Mybatis最入门---动态查询(foreach)http://www.bieryun.com/983.html

[一步是咫尺,一步即天涯]

本文,我们来介绍使用Mybatis提供的<foreach>标签实现我们某些循环增改删差的需求。官方文档中的内容过于简陋,于是,博主筛选出比较全面讲述foreach用法的的内容,并且配有例子。希望各位看官能够手动敲一遍下面的例子,达到快速学习的目的。

准备工作:

a.操作系统 :win7 x64

b.基本软件:MySQL,Mybatis,SQLyog

--------------------------------------------------------------------------------------------------------------------------------------------------------

我们先来叙述<foreach>中可以供我们使用的属性有哪些:

属性 描述
item 循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。
具体说明:在list和数组中是其中的对象,在map中是value。
该参数为必选。
collection 要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象没有默认的键。
当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:
如果User有属性List ids。入参是User对象,那么这个collection = "ids"
如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"
上面只是举例,具体collection等于什么,就看你想对那个元素做循环。
该参数为必选
separator 元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
open foreach代码的开始符号,一般设置为“(“和close=")"合用。常用在in(),values()时。该参数可选。
close foreach代码的关闭符号,一般设置为“)“和open="("合用。常用在in(),values()时。该参数可选。
index 在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。【这个具体用法见下文】

--------------------------------------------------------------------------------------------------------------------------------------------------------

【本文我们将给出完整的工程代码,请读者一定在本地运行一遍,加深理解】

1.首先,创建我们的Spring09工程,工程结构图如下:

2.pom文件内容如下:

[html] view plain copy

  1. <dependencies>
  2.         <dependency>
  3.             <groupId>junit</groupId>
  4.             <artifactId>junit</artifactId>
  5.             <version>4.12</version>
  6.             <scope>test</scope>
  7.         </dependency>
  8.         <dependency>
  9.             <groupId>org.mybatis</groupId>
  10.             <artifactId>mybatis</artifactId>
  11.             <version>3.3.1</version>
  12.         </dependency>
  13.         <dependency>
  14.             <groupId>mysql</groupId>
  15.             <artifactId>mysql-connector-java</artifactId>
  16.             <version>5.1.26</version>
  17.         </dependency>
  18.         <dependency>
  19.             <groupId>log4j</groupId>
  20.             <artifactId>log4j</artifactId>
  21.             <version>1.2.17</version>
  22.         </dependency>
  23.     </dependencies>

3.数据库配置文件jdbc.properties内容如下:

[plain] view plain copy

  1. jdbc.driverClassName=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/mybatis
  3. jdbc.username=root
  4. jdbc.password=1234

4.日志配置文件log4j.properties内容如下:

[plain] view plain copy

  1. log4j.rootLogger=debug,stdout
  2. log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  3. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  4. log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

5.mybatis-config.xml配置文件内容如下:

[html] view plain copy

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6.     <properties resource="jdbc.properties"/>
  7.     <settings>
  8.         <setting name="logImpl" value="LOG4J"/>
  9.     </settings>
  10.     <typeAliases>
  11.         <package name="com.csdn.ingo.entity"/>
  12.     </typeAliases>
  13.     <environments default="development">
  14.         <environment id="development">
  15.             <transactionManager type="JDBC" />
  16.             <dataSource type="POOLED">
  17.                 <property name="driver" value="${jdbc.driverClassName}" />
  18.                 <property name="url" value="${jdbc.url}" />
  19.                 <property name="username" value="${jdbc.username}" />
  20.                 <property name="password" value="${jdbc.password}" />
  21.             </dataSource>
  22.         </environment>
  23.     </environments>
  24.     <mappers>
  25.           <mapper resource="mappers/UserInfoMapper.xml"/>
  26.            <mapper resource="mappers/UserMapper.xml"/>
  27.     </mappers>
  28. </configuration>

6.UserInfo.java文件内容如下:

[java] view plain copy

  1. @SuppressWarnings("serial")
  2. public class UserInfo implements Serializable {
  3.     private String userid;
  4.     private String department;
  5.     private String position;
  6.     private String mobile;
  7.     private String gender;
  8.     private String email;
  9.     private Departments depart;
  10. //set,get,构造函数,toString,请自行补充
  11. }

7.user.java文件内容如下:

[java] view plain copy

  1. @SuppressWarnings("serial")
  2. public class User implements Serializable{
  3.     private String id;
  4.     private String password;
  5. //set,get,构造函数,toString,请自行补充

}

 

8.SqlSessionFactoryUtil.java内容如下:

[java] view plain copy

  1. package com.csdn.ingo.util;
  2. import java.io.InputStream;
  3. import org.apache.ibatis.io.Resources;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  7. public class SqlSessionFactoryUtil {
  8.     private static SqlSessionFactory sqlSessionFactory;
  9.     public static SqlSessionFactory getSqlSessionFactory(){
  10.         if(sqlSessionFactory==null){
  11.             InputStream inputStream=null;
  12.             try{
  13.                 inputStream=Resources.getResourceAsStream("mybatis-config.xml");
  14.                 sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
  15.             }catch(Exception e){
  16.                 e.printStackTrace();
  17.             }
  18.         }
  19.         return sqlSessionFactory;
  20.     }
  21.     public static SqlSession openSession(){
  22.         return getSqlSessionFactory().openSession();
  23.     }
  24. }

--------------------------------------------------------------------------------------------------------------------------------

准备工作结束,马上开始我们的<foreach>讲解,请睁大眼见哦!

--------------------------------------------------------------------------------------------------------------------------------

一.参数为数组Array。

1.UserTest的单元测试方法为:

[java] view plain copy

  1. @Test
  2.     public void testForEachArray() {
  3.         try {
  4.             String[] sa = new String[]{"admin","customer","customer2"};
  5.             UserInfoDao userInfo = sqlSession.getMapper(UserInfoDao.class);
  6.             List<UserInfo> UIList = userInfo.selectUserInfoByForEachArray(sa);
  7.             for (UserInfo ui : UIList) {
  8.                 System.out.println(ui.toString());
  9.             }
  10.         } catch (Exception e) {
  11.             e.printStackTrace();
  12.         }
  13.     }

【注意】

2.UserInfoDao.java的内容如下:【注意这里接口的形参为数组类型】

[java] view plain copy

  1. public interface UserInfoDao {
  2.     List<UserInfo> selectUserInfoByForEachArray(String[] sa);
  3. }

3.UserInfoMapper.xml的内容如下:

[html] view plain copy

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.csdn.ingo.dao.UserInfoDao">
  6.     <resultMap type="userInfo" id="UserInfoResult">
  7.         <id property="userid" column="userid" />
  8.         <result property="department" column="department" />
  9.         <result property="position" column="position" />
  10.         <result property="mobile" column="mobile" />
  11.         <result property="gender" column="gender" />
  12.         <result property="email" column="email" />
  13.     </resultMap>
  14. <select id="selectUserInfoByForEachArray" resultMap="UserInfoResult">
  15.         select * from userinfo
  16.         <if test="array!=null">
  17.             where userid in
  18.             <foreach item="item" collection="array" index="index" open="("
  19.                 separator="," close=")">
  20.                 #{item}
  21.             </foreach>
  22.         </if>
  23.     </select>
  24. </mapper>

【解释】

a。这里的if标签能够判断出数组是否为空。但是没有判断出数组中的内容是否为空。即,当数组中有内容时或者数组为null时,该SQL语句能够正常执行,但是如果数组为空的话,if判断的结果为真,但foreach执行0次。这种情况下,Mybatis会组装出1条错误的sql语句。换句话说这里if是多余的。

b。这里collection属性配置为”array“

c。index在这条语句中未使用,所以是可以缺省的。移除也不会引起错误

d。open,close只会在开始与结尾出现一次。

e。separator会使用配置的”,“来每次间隔<foreach>标签内的内容。

f。#{item}中的item必须与<foreach>中的item属性的值”item“保持一致。

------------------------------

4.运行单元测试方法,应该能够看到如下输出:【各位看官可以自行变化数组内容,观察控制台输出】


-------------------------------------------------------------------------------------------------------------------------------------

二。参数为List

1.在UserTest中新增单元测试方法:

[java] view plain copy

  1. @Test
  2.     public void testForEachList() {
  3.         try {
  4.             List<String> userlist = new ArrayList<String>();
  5.             userlist.add("admin");
  6.             userlist.add("customer");
  7.             userlist.add("customer2");
  8.             UserInfoDao userInfo = sqlSession.getMapper(UserInfoDao.class);
  9.             List<UserInfo> UIList = userInfo.selectUserInfoByForEachList(userlist);
  10.             for (UserInfo ui : UIList) {
  11.                 System.out.println(ui.toString());
  12.             }
  13.         } catch (Exception e) {
  14.             e.printStackTrace();
  15.         }
  16.     }

2.在UserInfoDao.java增加接口内容如下:

[java] view plain copy

  1. List<UserInfo> selectUserInfoByForEachList(List<String> sl);

3.在UserInfoDaoMapper.xml中,增加如下内容:

[html] view plain copy

  1. <select id="selectUserInfoByForEachList" resultMap="UserInfoResult">
  2.         select * from userinfo
  3.         <if test="list!=null">
  4.             where userid in
  5.             <foreach item="item" collection="list" index="index" open="("
  6.                 separator="," close=")">
  7.                 #{item}
  8.             </foreach>
  9.         </if>
  10.     </select>

【解释】

a.与上面类似:这里的if标签能够判断出List是否为空。但是没有判断出List中的内容是否为空。即,当List中有内容时或者List为null时,该SQL语句能够正常执行,但是如果List为空的话,if判断的结果为真,但foreach执行0次。这种情况下,Mybatis会组装出1条错误的sql语句。换句话说这里if是多余的。

b。这里collection属性配置为”list“

c。index在这条语句中未使用,所以是可以缺省的。移除也不会引起错误

d。其他内容请参考上面array中的解释

-------------------------------

4.运行单元测试方法,应该能够看到如下输出:【各位看官可以自行变化数组内容,观察控制台输出】

-------------------------------------------------------------------------------------------------------------------------------------

三。参数为Map

1.在UserTest中新增单元测试方法:

[java] view plain copy

  1. @Test
  2.     public void testForEachMap() {
  3.         try {
  4.             Map<String, Object> map = new HashMap<String, Object>();
  5.             List<String> userlist = new ArrayList<String>();
  6.             userlist.add("admin");
  7.             map.put("userids", userlist);
  8.             UserInfoDao userInfo = sqlSession.getMapper(UserInfoDao.class);
  9.             List<UserInfo> UIList = userInfo.selectUserInfoByForEach(map);
  10.             for (UserInfo ui : UIList) {
  11.                 System.out.println(ui.toString());
  12.             }
  13.         } catch (Exception e) {
  14.             e.printStackTrace();
  15.         }
  16.     }

2.在UserInfoDao.java增加接口内容如下:

[java] view plain copy

  1. List<UserInfo> selectUserInfoByForEach(Map<String,Object> map);

3.在UserInfoDaoMapper.xml中,增加如下内容:

[html] view plain copy

  1. <select id="selectUserInfoByForEach" parameterType="Map"
  2.         resultMap="UserInfoResult">
  3.         select * from userinfo
  4.         <if test="userids!=null">
  5.             where userid in
  6.             <foreach item="ParamsId" collection="userids" index="index"
  7.                 open="(" separator="," close=")">
  8.                 #{ParamsId}
  9.             </foreach>
  10.         </if>
  11.     </select>

【解释】

a.与上面类似:这里的if标签能够判断出map中否包含userids这个key,其对应的value可以任意。但是没有判断出value中的内容是否为空。即,当value中有内容时或者key不存在时,该SQL语句能够正常执行,但是如果value为空的话,if判断的结果为真,但foreach执行0次。这种情况下,Mybatis会组装出1条错误的sql语句。换句话说这里if是多余的。

b.这里collection属性配置为map中list对应的key的值,而不是value或者”list“

c.各位看官请注意这里的#{ParamsId}是与属性item中的ParamsId对应的

----------------------------------

4.运行单元测试方法,应该能够看到如下输出:【各位看官可以自行变化数组内容,观察控制台输出】


-------------------------------------------------------------------------------------------------------------------------------------

四。特别的index
1.在UserTest中新增单元测试方法:

[java] view plain copy

  1. @Test
  2.     public void testForeachIndex() {
  3.         try {
  4.             Map<String, Object> map = new HashMap<String, Object>();
  5.             Map<String,Object> user=new HashMap<String, Object>();
  6.             user.put("1""aaa");
  7.             user.put("2""bbb");
  8.             user.put("3""ccc");
  9.             user.put("4""ddd");
  10.             user.put("5""eee");
  11.             map.put("map", user);
  12.             UserDao userDao = sqlSession.getMapper(UserDao.class);
  13.                         int re = userDao.insertUserByForEachIndex(map);
  14.             if(re==1){
  15.                 System.out.println("success");
  16.             }
  17.             sqlSession.commit();
  18.         } catch (Exception e) {
  19.             e.printStackTrace();
  20.         }
  21.     }

2.在UserDao.java增加接口内容如下:

[java] view plain copy

  1. public interface UserDao {
  2.     int insertUserByForEachIndex(Map<String,Object> map);
  3. }

3.在UserDaoMapper.xml中,增加如下内容:

[java] view plain copy

  1. <insert id="insertUserByForEachIndex">
  2.         insert into sysuser (id,password) values
  3.         <foreach collection="map" index="id" item="item" separator=","
  4.             open="" close="">
  5.             (#{id},#{item})
  6.         </foreach>
  7.     </insert>

【注释】

博主这里找了官方文档,其给出的解释是:当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。

这里我们又参考其他博文中给出的解释,设计上面的示例,供各位看官学习。

作为示例,请读者特别留心SQL语句中所诠释的官方文档的意思。即,index对应key,item对应value。

鉴于篇幅的关系,更多用法就请各位举一反三吧!

----------------------------------

4.运行单元测试方法,应该能够看到如下输出:

-------------------------------------------------------------------------------------------------------------------------------------

至此,Mybatis最入门---动态查询(foreach)结束

特别备注:

关于<foreach>的用法需要具体应用场景和大量的练习,才能运用自如,请各位客官开心的敲代码吧!

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
Java 数据库连接 数据库
mybatis查询数据,返回的对象少了一个字段
mybatis查询数据,返回的对象少了一个字段
35 8
|
9天前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
9天前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
2月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
61 0
|
3月前
|
Java 数据库连接 mybatis
Mybatis查询传递单个参数和传递多个参数用法
Mybatis查询传递单个参数和传递多个参数用法
53 11
|
3月前
|
SQL Java 数据库连接
mybatis动态SQL常用语法总结
MyBatis 使用 OGNL 表达式语言处理动态SQL,如 `if` 标签进行条件判断,`choose`、`when`、`otherwise` 实现多条件选择,`where`、`set` 管理SQL关键字,`trim` 提供通用修剪功能,`foreach` 遍历集合数据。`sql` 和 `include` 用于代码重用,`selectKey` 处理插入后的返回值。参数传递支持匿名、具名、列表、Map、Java Bean和JSON方式。注意SQL转义及使用合适的jdbcType映射Java类型。
73 7
MybatisPlus-标准CRUD制作,新增boolean save(T t),删除 ~ delete(int id),修改 ~ update(T t),根据id查询,T getById....
MybatisPlus-标准CRUD制作,新增boolean save(T t),删除 ~ delete(int id),修改 ~ update(T t),根据id查询,T getById....
|
4月前
|
Java 关系型数据库 数据库连接
技术好文共享:第一讲mybatis入门知识
技术好文共享:第一讲mybatis入门知识
32 6
|
4月前
|
Java 关系型数据库 MySQL
Mybatis入门之在基于Springboot的框架下拿到MySQL中数据
Mybatis入门之在基于Springboot的框架下拿到MySQL中数据
39 4
|
4月前
|
Java 程序员
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
浅浅纪念花一个月完成Springboot+Mybatis+Springmvc+Vue2+elementUI的前后端交互入门项目
45 1