美文网首页大数据开发
大数据开发:Mybatis 结果映射器ResultMap

大数据开发:Mybatis 结果映射器ResultMap

作者: 成都加米谷大数据 | 来源:发表于2021-06-28 17:36 被阅读0次

    在大数据基础部分的课程当中,Mybatis作为重要的一个组件工具,是必学的。而Mybatis的诸多知识点,尤其是涉及到内部的概念细节,是尤其需要搞清楚的。今天的大数据开发基础学习分享,我们来讲讲Mybatis 结果映射器ResultMap。

    resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

    resultMap 可以将查询到的复杂数据,比如多张表的数据、一对一映射、一对多映射等复杂关系聚合到一个结果集当中。

    ResultMap 是如何进行映射的?

    1、 Getter/Setter 注入

    我们声明一个数据库对应的实体类:

    /**

    * @author felord.cn

    * @since 16:50

    **/

    @Data

    public class Employee implements Serializable {

        private static final long serialVersionUID = -7145891282327539285L;

        private String employeeId;

        private String employeeName;

        private Integer employeeType;

    }

    那么它对应的 resultMap 为:

    <mapper namespace="cn.felord.mybatis.mapper.EmployeeMapper">

        <resultMap id="EmployeeMap" type="cn.felord.mybatis.entity.Employee">

            <id column="employee_id" property="employeeId"/>

            <result column="employee_name" property="employeeName"/>

            <result column="employee_type" property="employeeType"/>

        </resultMap>

    </mapper>

    我们来解释这些配置的属性:

    <mapper namespace="全局唯一的名称空间">

        <resultMap id="本namespace下唯一" type="对应映射的实体">

            <id column="数据库主键字段名或者别名,使用它提高整体性能" property="对应实体属性"/>

            <result column="数据库字段名或者别名" property="对应实体属性"/>

        </resultMap>

    </mapper>

    以上方式是通过 Getter 和 Setter 方法进行注入,也就是实体类必须有无参构造,对应属性必须有Getter 和 Setter 方法。

    2、构造注入

    Getter 和 Setter 方法进行注入是我们最常用的方式。但是 Mybatis 同样支持构造注入,如果 Employee 存在如下构造方法:

    public Employee(String employeeId, String employeeName, Integer employeeType) {

        this.employeeId = employeeId;

        this.employeeName = employeeName;

        this.employeeType = employeeType;

    }

    那么对应的 resultMap 可以这样写:

    <mapper namespace="cn.felord.mybatis.mapper.EmployeeMapper">

        <resultMap id="EmployeeMap" type="cn.felord.mybatis.entity.Employee">

            <constructor>

                <idArg column="employee_id" javaType="String"/>

                <arg column="employee_name" javaType="String"/>

                <arg column="employee_type" javaType="String"/>

            </constructor>

        </resultMap>

    </mapper>

    细心的同学发现这里并没有 property 属性,其实当你不声明property 属性时会按照构造方法的参数列表顺序进行注入。

    在 Mybatis 3.4.3 引入了 name 属性后我们就可以打乱 constructor 标签内的 arg 元素的顺序了。

    <mapper namespace="cn.felord.mybatis.mapper.EmployeeMapper">

        <resultMap id="EmployeeConstructorMap" type="cn.felord.mybatis.entity.Employee">

            <constructor>

                <idArg column="employee_id" javaType="String" name="employeeId"/>

                <!-- 你可以不按参数列表顺序添加-->

                <arg column="employee_type" javaType="Integer" name="employeeType"/>

                <arg column="employee_name" javaType="String" name="employeeName"/>

            </constructor>

        </resultMap>

    </mapper>

    3、继承关系

    像 Java 中的类一样,resultMap 也是可以继承的。

    那么 RegularEmployee 的 resultMap 就可以这么写:

    <resultMap id="RegularEmployeeMap" extends="EmployeeMap" type="cn.felord.mybatis.entity.RegularEmployee">

        <result column="level" property="level"/>

        <result column="job_number" property="jobNumber"/>

        <association property="department" javaType="cn.felord.mybatis.entity.Department">

            <id column="department_id" property="departmentId"/>

            <result column="department_name" property="departmentName"/>

            <result column="department_level" property="departmentLevel"/>

        </association>

    </resultMap>

    跟 Java 的继承关键字一样使用 extends 来进行继承。

    4、一对一关联

    明眼人会看出来上面最后一个 resultMap 示例中有一个 association 标签。这个用来做什么用呢?打个比方,每一个正式员工 RegularEmployee会对应一个部门 Department,业务中会有把这种 一对一 关系查询出来的需求。所以 association 就派上了用场。

    <resultMap id="RegularEmployeeMap" extends="EmployeeMap" type="cn.felord.mybatis.entity.RegularEmployee">

        <result column="level" property="level"/>

        <result column="job_number" property="jobNumber"/>

        <association property="属性名称" javaType="对应的Java类型">

            <id column="department_id" property="departmentId"/>

            <result column="department_name" property="departmentName"/>

            <result column="department_level" property="departmentLevel"/>

        </association>

    </resultMap>

    association 可以继续嵌套下去,有可能关联的对象中还有一对一关系。

    5、一对多关联

    有一对一关联,自然会有一对多关联。我们反客为主,一个部门有多个员工,我们可能需要查询一个部门的信息以及所有员工的信息装载到 DepartmentAndEmployeeList中去。

    /**

    * @author felord.cn

    * @since 15:33

    **/

    public class DepartmentAndEmployeeList extends Department {

        private static final long serialVersionUID = -2503893191396554581L;

        private List<Employee> employees;

        public List<Employee> getEmployees() {

            return employees;

        }

        public void setEmployees(List<Employee> employees) {

            this.employees = employees;

        }

    }

    我们可以在 resultMap 中使用 collection 关键字来处理一对多映射关系:

    <resultMap id="DepartmentAndEmployeeListMap" extends="DepartmentMap"

               type="cn.felord.mybatis.entity.DepartmentAndEmployeeList">

        <collection property="employees" ofType="cn.felord.mybatis.entity.RegularEmployee">

            <id column="employee_id" property="employeeId"/>

            <result column="employee_name" property="employeeName"/>

            <result column="level" property="level"/>

            <result column="job_number" property="jobNumber"/>

        </collection>

    </resultMap>

    6、鉴别器

    大家都知道,员工并不都是正式工,还有临时工。有时候我们也期望能够将这两种区分开来,至于原因你懂的。不深入讨论这个问题了。就这个需求而言我们的映射关系又复杂了,我们需要根据某个条件来判断哪条数据是正式工,哪条数据是临时工,然后分别装入下面这个实体类的 regularEmployees、temporaryEmployees中。

    /**

    * @author felord.cn

    * @since 15:33

    **/

    public class DepartmentAndTypeEmployees extends Department {

        private static final long serialVersionUID = -2503893191396554581L;

        private List<RegularEmployee> regularEmployees;

        private List<TemporaryEmployee> temporaryEmployees;

        // getter setter

    }

    鉴别器(discriminator)元素就是被设计来应对这种情况的,另外也能处理其它情况,例如类的继承层次结构。鉴别器的概念很好理解——它很像 Java 语言中的 switch 语句。

    为此我们需要在 Employee 类中增加一个 int类型的 employeeType属性来区分正式工和临时工,其中 1代表正式工,而 0代表临时工。然后我们来编写查询 DepartmentAndTypeEmployees 的 resultMap :

    <resultMap id="DepartmentAndTypeEmployeesMap" extends="DepartmentMap"

               type="cn.felord.mybatis.entity.DepartmentAndTypeEmployees">

        <collection property="regularEmployees" ofType="cn.felord.mybatis.entity.RegularEmployee">

            <discriminator javaType="int" column="employee_type">

                <case value="1">

                    <id column="employee_id" property="employeeId"/>

                    <result column="employee_name" property="employeeName"/>

                    <result column="employee_type" property="employeeType"/>

                    <result column="level" property="level"/>

                    <result column="job_number" property="jobNumber"/>

                </case>

            </discriminator>

        </collection>

        <collection property="temporaryEmployees" ofType="cn.felord.mybatis.entity.TemporaryEmployee">

            <discriminator javaType="int" column="employee_type">

                <case value="0">

                    <id column="employee_id" property="employeeId"/>

                    <result column="employee_name" property="employeeName"/>

                    <result column="employee_type" property="employeeType"/>

                    <result column="company_no" property="companyNo"/>

                </case>

            </discriminator>

        </collection>

    </resultMap>

    切记一定是先声明 DepartmentAndTypeEmployees的两个 List ,然后在 collection 标签内部使用 discriminator 标签。

    关于大数据开发基础,Mybatis 结果映射器ResultMap,以上就为大家做了基本的介绍了。在现有的大数据生态体系当中,Mybatis是值得去学的,也是实际开发当中常常会用到的。

    相关文章

      网友评论

        本文标题:大数据开发:Mybatis 结果映射器ResultMap

        本文链接:https://www.haomeiwen.com/subject/xptcultx.html