下面显示的是元素的一些属性:MyBatis学习笔记-MyBatis映射器/20190118113710970.png)
1. update元素和delete元素
- 首先在映射接口中添加用于更新和删除的方法 - 1 
 2
 3
 4- //更新方法 
 public boolean updateEmp(Employee emp);
 //删除方法
 public boolean deleteEmpById(Integer id);
- 然后在映射器文件中添加对应的sql配置信息 - 1 
 2
 3
 4
 5
 6
 7- <!-- 参数类型可以省略 --> 
 <update id="updateEmp" parameterType="com.atguigu.mybatis.bean.Employee">
 update tbl_employee set last_name=#{lastName},gender=#{gender},email=#{email} where id=#{id}
 </update>
 <delete id="deleteEmpById">
 delete from tbl_employee where id=#{id}
 </delete>
- 进行测试 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 public void test02() throws IOException {
 //1.根据MyBatis的配置文件,即mybatis-config.xml创建SqlSessionFactory
 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
 //2.获取session实例,能直接执行*已经映射的SQL语句*
 SqlSession session = sqlSessionFactory.openSession(false);//设置默认不提交
 try {
 //3.获取接口的实现类对象
 EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
 
 //4.测试删除方法
 boolean isDelete = employeeMapper.deleteEmpById(3);//输出true或者false
 System.out.println(isDelete);
 
 //5.手动提交
 session.commit();
 } finally {
 //4.关闭会话session
 session.close();
 }
 }
2. insert元素-插入语句
2.1 简单应用
- 首先在映射接口中添加用于插入的方法 - 1 
 2- //增加方法 
 public void addEmp(Employee emp);
- 然后在映射器文件中添加对应的sql配置信息 - 1 
 2
 3- <insert id="addEmp"> 
 insert into tbl_employee(last_name,gender,email) values(#{lastName},#{gender},#{email})
 </insert>
- 测试代码 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 public void test02() throws IOException {
 //1.根据MyBatis的配置文件,即mybatis-config.xml创建SqlSessionFactory
 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
 //2.获取session实例,能直接执行*已经映射的SQL语句*
 SqlSession session = sqlSessionFactory.openSession(false);//设置默认不提交
 try {
 //3.获取接口的实现类对象
 EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
 //4.测试添加
 Employee emp = new Employee(null, "张三", "1", "zhangsan@gmail.com");
 employeeMapper.addEmp(emp);
 //5.手动提交
 session.commit();
 } finally {
 //4.关闭会话session
 session.close();
 }
 }
2.2 获取自增主键的值
MySQL支持自增主键,自增主键值的获取,MyBatis也是利用statement.getGenreatedKey();
MyBatis使用insert元素的useGenreatedKeys=”true”来使用自增主键获取主键值策略;
使用insert元素的keyProperty来指定对应的主键属性,也就是MyBatis获取到主键值以后,将这个值封装给javaBean的对应属性。
- 修改映射器文件中的insert元素 - 1 
 2
 3- <insert id="addEmp" useGeneratedKeys="true" keyProperty="id"> 
 insert into tbl_employee(last_name,gender,email) values(#{lastName},#{gender},#{email})
 </insert>
- 测试代码 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 public void test02() throws IOException {
 //1.根据MyBatis的配置文件,即mybatis-config.xml创建SqlSessionFactory
 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
 //2.获取session实例,能直接执行*已经映射的SQL语句*
 SqlSession session = sqlSessionFactory.openSession(false);//设置默认不提交
 try {
 //3.获取接口的实现类对象
 EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
 //4.测试添加
 Employee emp = new Employee(null, "张三", "1", "zhangsan@gmail.com");
 employeeMapper.addEmp(emp);
 //输出员工的id
 System.out.println(emp.getId());
 //5.手动提交
 session.commit();
 } finally {
 //4.关闭会话session
 session.close();
 }
 }
3. select元素-查询语句
3.1 参数处理
3.1.1单个参数
比如我要根据employee的id值来查询对应的员工,这时候对应的查询方法的参数只有一个,就是id值。在映射器中的对应SQL语句中,#{参数名}中的参数名MyBatis不做特殊处理,也就是该参数名可以随便取名。MyBatis学习笔记-MyBatis映射器/20190118090938321.png)
3.1.2 多个参数
3.1.2.1 使用注解传递多个参数
- 首先在映射接口中定义如下方法 - 1 
 2- //根据员工id和姓名查询员工 
 public Employee gerEmpByIdAndName(Integer id, String lastName);
- 然后在映射器文件中配置如下SQL - 1 
 2
 3- <select id="gerEmpByIdAndName" resultType="com.atguigu.mybatis.bean.Employee"> 
 select id,last_name,gender,email from tbl_employee where id=#{id} and last_name=#{lastName}
 </select>
- 运行测试之后会报如下错误 - 1 - Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [0, 1, param1, param2] - MyBatis在处理传入的多个参数时,会将多个参数封装成一个Map集合,对应的键值为: 
 key:param1…paramN,或者参数的索引0…N
 value:我们传入的参数值
 #{}就是从map中获取指定的key值,所以我们应该传入key值而不是value值。
解决:
使用命名参数,即明确指定封装参数时map的key,封装后的map集合的key值为使用@Param注解指定的值,value为参数值。
修改映射接口,指定map集合的键即可:
| 1 | //根据员工id和姓名查询员工 | 
3.1.2.2 通过POJO传递多个参数
- 存在一个POJO-Employee MyBatis学习笔记-MyBatis映射器/20190118095129429.png) 
- 此时在映射接口定义如下方法: - 1 
 2- //根据POJO查询员工 
 public Employee getEmpByBean(Employee emp);
- 在映射器配置如下SQL语句,这里是通过传入的Java Bean的id和lastName来查询。 - 1 
 2
 3- <select id="getEmpByBean" resultType="com.atguigu.mybatis.bean.Employee"> 
 select id,last_name,gender,email from tbl_employee where id=#{id} and last_name=#{lastName}
 </select>
- 测试代码 MyBatis学习笔记-MyBatis映射器/20190118095934798.png) - 3.1.2.3 通过Map集合传递多个参数
- 在映射接口定义如下方法 - 1 
 2- //根据Map集合来查询员工 
 public Employee getEmpByMap(Map<String, Object> map);
- 在映射器中配置SQL信息 - 1 
 2
 3- <select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee"> 
 select id,last_name,gender,email from tbl_employee where id=#{id} and last_name=#{lastName}
 </select>
- 测试代码 MyBatis学习笔记-MyBatis映射器/20190118100810622.png) - 3.1.2.4 混合使用MyBatis学习笔记-MyBatis映射器/20190118101635841.png) 
 注意:集合和数组都有默认的key。- 3.2 #{}与${}的异同- 相同点:两者都可以获取map中的值或者pojo对象属性的值。 
 不同点:
- #{}是以预编译的形式,将参数设置到sql语句中,类似于PreparedStatement,它可以防止sql注入。 
- ${}是直接将取出的值拼接在sql语句中,类似于Statement,可能引发安全问题。 - 下面演示一下: - 映射器文件的sql配置如下:1 
 2
 3<select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee"> 
 select id,last_name,gender,email from tbl_employee where id=#{id} and last_name=#{lastName}
 </select>
 
- 映射器文件的sql配置如下:
- 测试代码 - 1 
 2
 3
 4
 5
 6
 7- EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); 
 //4.测试查询方法
 Map<String,Object> map = new HashMap<>();
 map.put("id", "1");
 map.put("lastName", "Tom");
 Employee emp = employeeMapper.getEmpByMap(map);
 System.out.println(emp);
- 运行结果 MyBatis学习笔记-MyBatis映射器/2019011811235849.png) 
 从输出的sql语句可以看出占位符?是存在的。
下面我们修改一下映射器文件的配置信息,更改为id=${id}:
| 1 | <select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee"> | 
再次测试的输出结果为:MyBatis学习笔记-MyBatis映射器/2019011811270421.png)
3.3 ${}的更多用法
比如我们需要按照年份进行分表拆分,然后使用传入的年份生成对应的表名,如
| 1 | select * from ${year}_salary where xxx; | 
又比如我们通过字段名来对表的字段进行排序,那么我们也可以通过$来实现。如
| 1 | select * from tbl_employee order by ${last_name} ${order} | 
显然,原生JDBC不支持占位符的地方我们就可以使用${}来进行取值。
3.4 #{}的更多用法
#{}还可以规定参数的一些规则,比如javaType、 jdbcType、 mode、 numericScale、
resultMap、 typeHandler、 jdbcTypeName。
下面来讲一下jdbcType的用法。
在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理(MyBatis默认将null设置为OTHER类型),比如Oracle数据库就无法识别OTHER类型。
我们可以在某个插入为null的数据来使用jdbcType设置。比如我要进入如下数据库操作:
| 1 | <insert id="addEmp" useGeneratedKeys="true" keyProperty="id"> | 
但是我在传入数据的时候,email的值是null,那么Oracle数据库是无法识别而报错的。我们可以更改为如下语句则可以解决这个问题:MyBatis学习笔记-MyBatis映射器/20190118114725199.png)
上面的配置只使用单条sql语句。我们可以在全局配置文件设置settings来实现全局配置,即:MyBatis学习笔记-MyBatis映射器/20190118115056705.png)
3.5 查询返回数据封装
3.5.1 List封装查询到的数据
- 在映射接口编写查询方法 - 1 
 2- //使用List封装查询到的数据 
 public List<Employee> getEmpsByLastNameLike(String lastName);
- 在映射器文件中编写指定的SQL配置,注意:返回类型是Employee对象 - 1 
 2
 3- <select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee"> 
 select id,last_name,gender,email from tbl_employee where last_name like #{lastName}
 </select>
- 测试代码 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 public void test04() throws IOException {
 //1.根据MyBatis的配置文件,即mybatis-config.xml创建SqlSessionFactory
 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
 //2.获取session实例,能直接执行*已经映射的SQL语句*
 SqlSession session = sqlSessionFactory.openSession(false);//设置默认不提交
 try {
 //3.获取接口的实现类对象
 EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
 //4.查询
 List<Employee> empsList = employeeMapper.getEmpsByLastNameLike("%张%");
 for (Employee employee : empsList) {
 System.out.println(employee);
 }
 //5.手动提交
 session.commit();
 } finally {
 //4.关闭会话session
 session.close();
 }
 }
3.5.2 Map封装查询到的数据
需求1:将Employee中的属性封装到一个Map中,其中key为Employee中的属性名,value为对应的值。
- 编写映射接口方法 - 1 
 2- //使用Map封装查询到的数据 
 public Map<String, Object> getEmpsByIdReturnMap(Integer id);
- 在映射器文件编写对应的SQL配置 - 1 
 2
 3
 4- <!-- 返回类型是Map集合,map是系统自定义的别名 --> 
 <select id="getEmpsByIdReturnMap" resultType="map">
 select * from tbl_employee where id=#{id}
 </select>
- 测试代码 - 1 
 2
 3
 4- EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class); 
 //4.查询
 Map<String, Object> empMap = employeeMapper.getEmpsByIdReturnMap(1);
 System.out.println(empMap);
- 运行结果 - 1 - {gender=1, last_name=Tom, id=1, email=shotozheng.com} - 需求2:将多个Employee对象封装到Map集合中,其中key为Employee中的id属性值,value为Employee对象。 
- 同样需要在映射接口编写方法 - 1 
 2- ("id") 
 public Map<Integer,Employee> getEmpsByLastNameLikeReturnMap(String lastName);- 注意:MapKey在于指定返回的Map集合的key为Employee的属性id 
- 在映射器接口编写SQL配置 - 1 
 2
 3
 4- <!-- 注意:这里的返回类型是Employee对象 --> 
 <select id="getEmpsByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee">
 select * from tbl_employee where last_name like #{lastName}
 </select>
- 运行测试即可,不再赘述。 
4. resultMap元素
比如我们在定义Java Bean时,POJO的属性名若与数据库表的字段名不一样则会导致查询出来的数据为null。我们之前是用通过给SQL的的字段命和POJO对应属性一样的名称或者通过驼峰命名法来处理这个问题。但是这些可能会导致SQL语句不好理解或者POJO中的属性名不符合驼峰命名法规范等问题。
那么现在我们可以使用resultMap来定义映射规则来处理这个问题,当然它还可以进行级联更新和定制类型转化器等功能。定义映射规则就是SQL到Java Bean的映射关系定义。
下面演示一下resultMap自定义结果的功能:
- 创建一个POJO类Employee - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19- public class Employee { 
 private Integer id;
 private String lastName;
 private String gender;
 private String email;
 
 public Employee() {
 super();
 }
 public Employee(Integer id, String lastName, String gender, String email) {
 super();
 this.id = id;
 this.lastName = lastName;
 this.gender = gender;
 this.email = email;
 }
 //getter,setter,toString....
 }- 注意:类中lastName属性对应的数据库表tbl_employee字段last_name 
- 在映射接口EmployeePlus中定义如下方法 - 1 - public Employee getEmpById(Integer id); 
- 在映射器文件EmployeePlus.xml文件定义如下SQL配置 MyBatis学习笔记-MyBatis映射器/20190118162111237.png) 
- 测试代码 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 public void test05() throws IOException {
 //1.根据MyBatis的配置文件,即mybatis-config.xml创建SqlSessionFactory
 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
 //2.获取session实例,能直接执行*已经映射的SQL语句*
 SqlSession session = sqlSessionFactory.openSession(false);//设置默认不提交
 try {
 //3.获取接口的实现类对象
 EmployeeMapperPlus mapper = session.getMapper(EmployeeMapperPlus.class);
 //4.查询
 Employee emp = mapper.getEmpById(1);
 System.out.println(emp);
 //5.手动提交
 session.commit();
 } finally {
 //4.关闭会话session
 session.close();
 }
 }
- 运行结果 MyBatis学习笔记-MyBatis映射器/20190118162346688.png) 
 在进行了自定义映射配置之后,即使Java Bean的属性名与数据库表的字段不一样,也可以形成映射关系。
5. 关联查询
需求:在查询出员工对象的同时,查询出该员工所在的部门。
5.1 级联属性封装结果集
- 创建两个Java Bean,分别为员工类Employee和部门类Department - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- public class Employee { 
 private Integer id;
 private String lastName;
 private String gender;
 private String email;
 private Department dept; //引用部门对象
 
 public Employee() {
 super();
 }
 public Employee(Integer id, String lastName, String gender, String email) {
 super();
 this.id = id;
 this.lastName = lastName;
 this.gender = gender;
 this.email = email;
 }
 //getter,setter,toString
 }- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- public class Department { 
 private Integer id; //部门编号
 private String departmentName; //部门名称
 
 public Department() {
 super();
 }
 public Department(Integer id, String departmentName) {
 super();
 this.id = id;
 this.departmentName = departmentName;
 }
 //getter,setter,toString....
 }
- 创建对应的数据库表tbl_employee和tbl_dept - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- CREATE TABLE tbl_employee ( 
 id int(11) NOT NULL AUTO_INCREMENT,
 last_name varchar(255) DEFAULT NULL,
 gender char(1) DEFAULT NULL,
 email varchar(255) DEFAULT NULL,
 d_id int(11) DEFAULT NULL,
 PRIMARY KEY (id),
 KEY FK_tbl_employee (d_id),
 CONSTRAINT FK_tbl_employee FOREIGN KEY (d_id) REFERENCES tbl_dept (id)
 )- 1 
 2
 3
 4- CREATE TABLE tbl_dept( 
 id INT(11) PRIMARY KEY AUTO_INCREMENT,
 dept_name VARCHAR(255)
 )
- 映射接口EmployeeMapperPlus中定义如下方法 - 1 - public Employee getEmpAndDept(Integer id); 
- 映射器文件EmployeeMapperPlus.xml进行如下配置 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- <!-- 联合查询,**级联属性封装结果集** --> 
 <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
 <id column="id" property="id"/>
 <result column="last_name" property="lastName"/>
 <result column="gender" property="gender"/>
 <result column="email" property="email"/>
 <!-- 下面的是关于部门表的内容,可以使用Employee的属性dept来引用 -->
 <result column="did" property="dept.id"/>
 <result column="dept_name" property="dept.departmentName"/>
 </resultMap>
 <!-- 查询两个表的所有字段的值 resultMap的值即为上方resultMap元素的id-->
 <select id="getEmpAndDept" resultMap="MyDifEmp">
 SELECT e.id id, e.last_name last_name,e.gender gender, e.email email,
 e.d_id d_id, d.id did, d.dept_name dept_name FROM tbl_employee e, tbl_dept d
 WHERE e.d_id=d.id AND e.id=#{id}
 </select>
- 运行测试 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 public void test05() throws IOException {
 //1.根据MyBatis的配置文件,即mybatis-config.xml创建SqlSessionFactory
 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
 //2.获取session实例,能直接执行*已经映射的SQL语句*
 SqlSession session = sqlSessionFactory.openSession(false);//设置默认不提交
 try {
 //3.获取接口的实现类对象
 EmployeeMapperPlus mapper = session.getMapper(EmployeeMapperPlus.class);
 //4.查询
 Employee emp = mapper.getEmpAndDept(1);
 System.out.println(emp);//连同部门信息也会打印出来
 //5.手动提交
 session.commit();
 } finally {
 //4.关闭会话session
 session.close();
 }
 }- 刚才对映射器文件EmployeeMapperPlus.xml进行配置时使用的是级联属性封装结果集 的方式,下面我们也可以使用association的方式来定义关联的单个对象的封装规则。 - 5.2 association元素- 5.2.1 association嵌套结果集- 在原有的基础上,对映射器文件EmployeeMapperPlus.xml的resultMap元素进行如下更改配置: MyBatis学习笔记-MyBatis映射器/20190118174753484.png) - 5.2.2 association分步查询- 我们还可以使用association来进行分步查询。 
具体思路:
- 先按照员工的id去查询员工的信息
- 根据查询员工信息中的d_id值去部门表查出部门信息
- 将查询到的部门信息设置到员工信息中
具体步骤:
- 为了根据员工的id去查询员工的信息,我们需要先在映射接口EmployeeMapperPlus中定义如下方法: - 1 - public Employee getEmpByIdStep(Integer id); 
- 然后需要在映射器文件EmployeeMapperPlus.xml文件进行如下配置 - 1 
 2
 3
 4- <!-- 查出员工的信息 --> 
 <select id="getEmpByIdStep" resultMap="MyEmpByStep">
 select * from tbl_employee where id=#{id}
 </select>
- 因为需要根据员工信息中的d_id值去部门表查出部门信息 ,所以现在需要在映射接口DepartmentMapper中定义如下方法: - 1 - public Department getDeptById(Integer id); 
- 同样地,在映射器文件中进行如下配置: - 1 
 2
 3
 4
 5- <mapper namespace="com.atguigu.mybatis.mapper.DepartmentMapper"> 
 <select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department">
 select id,dept_name departmentName from tbl_dept where id=#{id}
 </select>
 </mapper>
- 对映射器文件EmployeeMapperPlus.xml做如下的resultMap元素配置: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19- <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep"> 
 <!-- 员工基本属性信息映射配置 -->
 <id column="id" property="id"/>
 <result column="last_name" property="lastName"/>
 <result column="email" property="email"/>
 <result column="gender" property="gender"/>
 
 <!-- association定义关联对象的封装规则
 property的内容的Employee关联的对象属性名dept
 select表明当前属性调用select指定的方法查出的结果,内容的namespace+方法id
 column指定将哪一列的值传给这个方法,这里要根据d_id去查询部门信息,所以为d_id
 流程:使用select指定的方法并通过传入column指定的这列参数的值去查出对象,
 并封装给property指定的属性,即dept
 -->
 <association property="dept"
 select="com.atguigu.mybatis.mapper.DepartmentMapper.getDeptById"
 column="d_id">
 </association>
 </resultMap>
- 运行测试 MyBatis学习笔记-MyBatis映射器/20190118202443754.png) - 5.2.3 延迟加载问题- 从以上的输出结果可以知道,系统会进行通过员工id查询员工信息,并且通过员工的id去查询对应的部门号。但是如果我们在未使用到部门的信息时,也就是我们只输出员工本身的一些与部门无关的信息,系统依旧会进行部门信息的查询。这样会浪费系统资源,我们可以通过设置延迟加载来处理这个问题。 
在全局配置文件进行如下配置:
| 1 | <!-- 开启延迟加载和关闭属性按需加载 --> | 
5.3 collection元素
需求:根据id查询部门的时候,同时查询出该部门的所有员工。
5.3.1 collection嵌套结果集
- 更改JavaBean类Department,增加字段以及对应的getter和setter方法。具体如下所示: MyBatis学习笔记-MyBatis映射器/20190118212716485.png) 
- 在映射接口DepartmentMapper中添加如下方法 - 1 - public Department getDeptAndEmpsByDeptId(Integer id); 
- 在映射器文件DepartmentMapper.xml进行如下配置 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- <!-- type的内容即为返回值类型,即查询到的部门对象 --> 
 <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept">
 <id column="did" property="id"/>
 <result column="dept_name" property="departmentName"/>
 <!-- collection定义关联集合类型的属性的封装规则
 ofType指定集合里面的元素类型
 -->
 <collection property="emps" ofType="com.atguigu.mybatis.bean.Employee">
 <!-- 定义这个集合中元素的封装规则,这里的是员工 -->
 <id column="eid" property="id"/>
 <result column="last_name" property="lastName"/>
 <result column="email" property="email"/>
 <result column="gender" property="gender"/>
 </collection>
 </resultMap>
 <select id="getDeptAndEmpsByDeptId" resultMap="MyDept">
 select d.id did,d.dept_name,e.id eid,e.last_name,e.email,e.gender
 from tbl_dept d
 LEFT JOIN tbl_employee e
 ON d.id=e.d_id
 WHERE d.id=#{id}
 </select>
- 测试代码 MyBatis学习笔记-MyBatis映射器/20190118215543404.png) - 5.3.2 collection分步查询- 具体思路: 
- 先按照部门的id去查询部门的信息 
- 根据查询到的部门信息中的id值去查询员工表的员工信息 
- 将查询到的员工信息设置到部门信息的属性集合中 
具体步骤:
- 在映射接口文件DepartmentMapper中定义如下方法,即根据部门id查询部门信息: - 1 - public Department getDeptByIdStep(Integer id); 
- 在映射器文件DepartmentMapper.xml进行如下配置: - 1 
 2
 3- <select id="getDeptByIdStep" resultMap="MyDeptStep"> 
 select id,dept_name departmentName from tbl_dept where id=#{id}
 </select>
- 在映射接口EmployeeMapperPlus中定义如下方法,即根据部门id查询所有员工: - 1 - public List<Employee> getEmpsByDeptId(Integer deptId); 
- 在映射器EmployeeMapperPlus.xml中配置如下信息 - 1 
 2
 3
 4
 5- <!--注意:如果Employee中的字段与数据库表的字段名不一样,需要给字段命和POJO中对应属性一样的名称, 
 比如下面的last_name字段必须需命名为lastName,否则无法完成一一映射。-->
 <select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
 select id,last_name lastName,gender,email from tbl_employee where d_id=#{deptId}
 </select>
- 在映射器文件DepartmentMapper.xml中配置resultMapper信息,完成关联对象的封装规则: MyBatis学习笔记-MyBatis映射器/20190118223234768.png) 
补充:我们上面的例子只在column属性中传递了一个部门的id值。如下图示:MyBatis学习笔记-MyBatis映射器/20190118223819667.png)
我们在分步查询时也可以进行多列传值,MyBatis会将多列的值封装为map进行传递。
格式为column=”{key1=column1,key2=column2}”
比如可以写成如下形式:MyBatis学习笔记-MyBatis映射器/20190118224103581.png)
其中的键deptId对应映射器EmployeeMapperPlus.xml中的SQL的传入的id名称。即MyBatis学习笔记-MyBatis映射器/20190118224300809.png)
6. sql 元素
sql元素的作用在于可以定义一条SQL的一部分,方便后面的SQL引用它。假设映射器文件中有如下配置信息:MyBatis学习笔记-MyBatis映射器/20190119165149425.png)
我们可以使用sql将其中的id,last_name lastName,gender,email抽取出来。如下所示:MyBatis学习笔记-MyBatis映射器/20190119165321942.png)
更改原有的配置信息,引用sql标签的配置。MyBatis学习笔记-MyBatis映射器/20190119165504999.png)
sql元素还支持变量的传递,映射器的配置信息如下:MyBatis学习笔记-MyBatis映射器/20190119170315143.png)
在include元素中定义了一个命名为e的变量,其值是SQL中标tbl_employee的别名emp,然后sql元素就能够使用这个变量名了。这个用法常用于多表查询并需要给不同表起别名的情况。