MyBatis | 映射文件之 ResultMap(一)

上一篇文章主要介绍了如何使用 resultType 来实现增删改查,但是如果需要实现更加复杂的查询语句,需要使用 ResultMap,下面我分两部分进行讲解。第一部分是最基本的规则配置,第二部分则是通过栗子说明如何进行更加复杂的查询操作

一、什么是 ResultMap?

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来, 并在一些情形下允许你做一些 JDBC 不支持的事情。 实际上,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。 ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。

可以看出,和 resultType 相比,ResultMap 可以处理更加复杂的映射关系,我们可以自由定制我们需要的映射规则,这也是我们想要的效果。

二、如何使用 ResultMap?

我们先创建两张相关联的表,employee 表和 department 表。其中,每个员工信息包含部门信息,具体操作是,employee 的 dept_id 关联 department 表的 id 字段,即 id 是 dept_id 的外键

employee表

department 表

然后创建两个 POJP 类,这在后面的测试中会用到
Department.java

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;
    }
        ...
}

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;
    }
        ...
}

我们可以看到,Employee 类中包含了 Department 类,对应了员工表中每个员工对应一个部门,而一个部门却可以有多个员工

1. 使用 resultMap 查询一张表

我们先自定义一个标签名为 的 sql 映射规则,之后在 sql 中调用这个规则


    
    
    
    




说明:

type:自定义规则的 JavaBean 类, 可以使用别名
id:为了后面方便引用的


column:指定列名
property:指定对应的 JavaBean 属性

除了主键以外的属性,都可以用 result 标签来标注。id 定义的主键底层会有优化,当然也可以都使用 result。如果不指定对应的列和属性, 即 id 和 result 标签都不配置,mybatis 也会帮我们自动封装,不过建议每个映射都自己对应

2. 使用 resulutMap 查询两张表

需求是,使用 sql 语句,查询出每个员工的信息,以及员工所在的部门信息,一个员工对应一个部门,即一对一关系

方法一:使用关联操作

我们先写好查询员工信息的 sql 语句,包括使用外键关联到的部门信息,此时我们使用 resultMap 自定义查询规则。使用关联查询, department 对象为在 Employee类 中给 Department 类设置的引用对象。




    
    
    
    
    
    
    
    
    


方法二:使用 assocation 定义单个对象的封装规则

sql 语句和方法一一致,我们使用另一种自定义 resultMap 的查询方式。使用 assocation 定义单个对象的封装规则
property:要将关联查询的用户信息映射到Orders中的哪个属性
javaType:指定这个联合对象的类型




    
    
    
    
    
    
    
        
        
    


方法三:使用 assocation 进行分布查询

分布查询的步骤如下:

  1. 先按照员工 id 查找员工信息,对应语句为 select * from employee where id = ?
  2. 根据查询到的员工信息中的 dept_id 查找部门信息,对应的语句为 select * from department where id = ?
  3. 将查询到的部门信息关联到与之对应的员工信息

①. 查询员工信息的配置


②. 查询部门信息的配置


③. 使用 assocation 自定义 resultMap
定义单个对象的封装规则
select:使用与该类(Employee)联合的类(Department)定义的方法(getDepartment,这里要使用全类名的方式给出,由于两个 sql 配置不在同一 mapper 下
column:指定将哪一列的值作为参数传给 select 属性定义的方法所需要的参数。注意:如果 sql 语句中列名使用别名,则 column 里面的值一定要和别名相同


     
     
     
     
     
     
     
     
     

④. 最后在查询语句中使用上述定义的 resultMap 配置文件


DepartmentMapper.java

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


3. 关于延迟加载

既然已经提到使用分布查询,那就不得不提到延迟加载,这种机制是建立在分布查询的基础上的

3.1 什么是延迟加载?

在没有使用延迟加载情况下,比如我们在 assocation 分布查询的基础上,只想查询出
员工的姓名, 那么 mybatis 在执行完第一条 sql 语句后(查询员工个人信息语句,此时已经查询出了员工姓名),还会接着执行第二条 sql 语句(查询员工部门信息)。很显然,这样会显得冗余,查询效率低下。

延迟加载:又称按需加载,在分布查询的基础上,mybaits 只会按照我们需要的数据进行查询,当没有涉及当需要查询关联表的数据时候,则停止查询。比如我们只需要查询出员工(Employee)的姓名,延迟加载会只执行第一条 sql 语句,此时已经查询出员工姓名了,此时立刻停止执行语句。

当我们只查询 Employee 的 lastName 属性,测试代码输出结果进行对比如下:

//使用延迟加载,只执行一条 sql 语句
DEBUG 07-27 00:38:19,927 ==>  Preparing: select * from employee where id = ?   (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:38:19,960 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:38:20,001 <==      Total: 1  (BaseJdbcLogger.java:159) 
Tom

//没有使用延迟加载,执行了两条 sql 语句
DEBUG 07-27 00:43:13,811 ==>  Preparing: select * from employee where id = ?   (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:43:13,846 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:43:13,862 ====>  Preparing: select * from department where id = ?   (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:43:13,862 ====> Parameters: 1(Integer)  (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:43:13,865 <====      Total: 1  (BaseJdbcLogger.java:159) 
DEBUG 07-27 00:43:13,865 <==      Total: 1  (BaseJdbcLogger.java:159) 
Tom


3.2 如何设置

只需要在总的配置文件 mybatis-config.xml 中,进行如下配置


    
    

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性,否则,每个属性会按需加载

三、参考

mybatis 官方文档

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