MyBatis | 映射文件之 ResultMap(二)

在上一篇文章 MyBatis | 映射文件之 ResultMap(一)中,简述了如何使用 ResultMap,以及如何使用 ResultMap 进行一对一的关联查询。这一篇我将说明如何使用 ResultMap 进行一对多的关联查询

一、说明与准备

为了便于学习,我仍然会贴出表结构和 POJO 的设计,下面是实验前的环境搭建

employee 的 dept_id 关联 department 表的 id 字段,即 id 是 dept_id 的外键。这和上一篇的创建是一致的

employee表

department 表

Employee.java

public class Employee {

    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;
    private Department department;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
        ...
}

Department:这里我设置了一个类型为 Employee 的 List 集合,对应数据库表中一个部门可以有多个员工

public class Department {

    private Integer id;
    private String departName;
    private List employees;
    
    public void setEmployees(List employees) {
        this.employees = employees;
    }
    
    public List getEmployees() {
        return employees;
    }
        ...
}


二、使用 ResultMap 进行一对多关联查询

需求是,使用 sql 语句,查询出每个部门的信息,以及每个部门所关联的员工信息。由于一个部门对应多个员工,即一对多,这里我们使用 LEFT JOIN 对字段进行连接

1. 使用 collection 进行两张表的关联查询

类似于上一篇中介绍的一对一的关联查询,不过上一篇中关联的是一个对象,不这里关联的是一个集合。至于 collection,我会结合代码进行讲解

①. 首先创建一个集合类
DepartmentMapper.java

public interface DepartmentMapper {
    public Department getDepartmentAndList(Integer id);
}



②. 配置 sql 映射文件
下面是 DepartmentMapper.xml 的配置信息,sql 语句如下,当然是使用外键关联


接下来写 resultMap 的配置:外层的 id 和 result 标签,是配置 Department 类(表)的,collection 标签里面的 id 和 result 标签,都是用来配置与 Department 类关联的 Employee 类(表)的。(PS:由于我在 mybatis.xml 主配置文件中配置了使用别名,因此类型都是以别名显示。否则需要全类名。)

collection 标签里定义的集合对象,这里定义的是 Employee 类型的集合
property:指定 Department 对象里面包含的 Employee 集合对象,即 List employees
ofType:指定集合的类型



    
    
    
    
    
    
        
        
        
        
    


③. 结果
测试语句我不写了,我们传入 Employee 的 id 为 1,直接贴出结果

Department [id=1, departName=开发部]
[Employee [id=1, lastName=Tom, [email protected], gender=0], 
Employee [id=2, lastName=Peter, [email protected], gender=1], 
Employee [id=7, lastName=ljk, [email protected], gender=1], 
Employee [id=15, lastName=lkj, [email protected], gender=2]]

同时贴出使用同样 sql 语句和同样 id 的数据库查询的结果

+-----+-------------+------+-----------+--------------+--------+
| did | depart_name | eid  | last_name | email        | gender |
+-----+-------------+------+-----------+--------------+--------+
|   1 | 开发部      |    1 | Tom       | [email protected]  |      0 |
|   1 | 开发部      |    2 | Peter     | [email protected] |      1 |
|   1 | 开发部      |    7 | ljk       | [email protected]  |      1 |
|   1 | 开发部      |   15 | lkj       | [email protected]  |      2 |
+-----+-------------+------+-----------+--------------+--------+

可以看到,使用 resultMap 查询出来的结果和数据库查询的结果一致,而且 Employee 确实是以 List 集合的形式出现的。

⭐⭐⭐遇到的坑:
在查询的过程中,遇到了一个毕竟大的坑,当时找了快几个小时╯︿╰,这里说明一下,防患于未来。。
先斩后奏把。column 里面的值一定要与查询出来的列名相一致, 如果使用列的别名, 则 column 的值就是列的别名

拿上面的 sql 为例,我们看一下使用别名查询出来的列名

| did | depart_name | eid | last_name | email | gender |

以 id 这个字段为例子,我们注意一下 resultMap 里面配置的两个 id 标签对应的 column 对应的值,可以看到对应的是 sql 语句(SELECT d.id did, e.id eid ... FROM department d...)中设置的别名 dideid


    
    ...
    
        
        ....
    

如果你没有设置别名(SELECT d.id, e.id ... FROM department d...),同时你在两个 id 标签的 column 直接填 id,那么就会出问题。。血的教训

| id | depart_name | id1 | last_name | email | gender |

不用别名查询出来的表的列名结构是这样的,如果真要用,可以这样配置。这样也是可以查询出结果的,不过并不推荐。还是使用别名把!!!


    
    ...
    
        
        ....
    


2. 使用 collection 进行两张表的分布查询

使用 association 进行分布查询,实则分三步:

  1. 先根据部门 id 查询出部门所有信息:select * from department where id = ?
  2. 根据部门查询出来的 id(外键),用于查询部门对应的多个员工信息:select * from employee where dept_id = ?
  3. 将员工信息关联到部门信息

先创建一个接口类

public interface DepartmentMapper {
    public Department getDepartmentStep(Integer id);
}

查询部门 Department 类的配置


查询员工 Employee 类的配置


配置 resultMap,注意 collection 中的 column 属性对应数据库中的列名


    
    
    
    
    
    
    

结果:

[Employee [id=1, lastName=Tom, [email protected], gender=0, department=null], 
Employee [id=2, lastName=Peter, [email protected], gender=1, department=null], 
Employee [id=7, lastName=ljk, [email protected], gender=1, department=null], 
Employee [id=15, lastName=lkj, [email protected], gender=2, department=null]]


3. 使用延迟加载

collection 标签中的延迟加载比较简单,直接在 collection 里面设置 fetchType 属性值为 lazy 即可
fetchType="lazy" 表示使用延迟加载
fetchType="eager" 表示立即加载


    ...
    
    

你可能感兴趣的:(MyBatis | 映射文件之 ResultMap(二))