MyBatis自定义映射关系ResultMap

MyBatis自定义映射关系ResultMap

1、准备工作

数据库创建

在这里插入图片描述

在这里插入图片描述

填入数据

在这里插入图片描述

在这里插入图片描述

实体类创建

public class Emp {
    private Integer eid;

    private String empName;

    private Integer age;

    private String sex;

    private String email;

    public Emp(Integer eid, String empName, Integer age, String sex, String email) {
        this.eid = eid;
        this.empName = empName;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    public Emp() {
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "eid=" + eid +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}
public class Dept {
    private Integer did;

    private String dName;

    public Dept() {
    }

    public Dept(Integer did, String dName) {
        this.did = did;
        this.dName = dName;
    }

    public Integer getDid() {
        return did;
    }

    public void setDid(Integer did) {
        this.did = did;
    }

    public String getdName() {
        return dName;
    }

    public void setdName(String dName) {
        this.dName = dName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "did=" + did +
                ", dName='" + dName + '\'' +
                '}';
    }
}

可以看到数据库中t_emp中的字段emp_name与实体类中的empName属性并不一致,这是如果不经过处理,MyBatis取到该字段的值之后就不会自动赋值到实体类的empName属性。

为了解决字段名和属性名不一致的情况,有三种方法

  • 为字段取别名,保持和属性名的一致

    select eid,emp_name empName,age,sex,email from t_emp
    
  • 设置全局配置,将_自动映射为驼峰

    <setting name="mapUnderscoreToCamelCase" value="true"/>
    
  • 使用resultMap自定义字段和属性的映射关系

    <resultMap id="empResultMap" type="emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
    </resultMap>
    

2、resultMap处理字段和属性的映射关系

要设置select标签中的resultMap属性,必须先用resultMap标签定义一个resultMap。

resultMap:设置自定义映射关系,有两个属性

  • id:唯一标识,不能重复
  • type:设置映射关系中的实体类类型

子标签:

  • id:设置主键的映射关系
  • result:设置普通属性的映射关系

id和resukt分别有两个相同属性:

  • property:设置映射关系中的属性名,必须是resultMap标签中type属性所设置的实体类中的属性名
  • column:设置映射关系中的字段名,必须是sql语句查询出的字段名
<resultMap id="empResultMap" type="emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
</resultMap>

<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
    select * from t_emp
</select>

3、多对一映射处理

public class Emp {
    private Integer eid;

    private String empName;

    private Integer age;

    private String sex;

    private String email;

    private Dept dept;
    //构造器和、get、set等
}

有三种方式

1>通过级联赋值处理多对一的关系

<resultMap id="EmpAndDeptResultMapOne" type="emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
    <result property="dept.did" column="did"></result>
    <result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid") Integer eid);-->
<select id="getEmpAndDept" resultMap="EmpAndDeptResultMapOne">
    select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>

2>通过association标签处理多对一的关系

  • 属性
    • property:需要处理多对一的映射关系的类的属性名
    • javaType:该属性的类型
  • 子标签
    • id:设置主键的映射关系
    • result:设置普通属性的映射关系
    • property:设置映射关系中的属性名,必须是resultMap标签中type属性所设置的实体类中的属性名
    • column:设置映射关系中的字段名,必须是sql语句查询出的字段名
<resultMap id="EmpAndDeptResultMapTwo" type="emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
    <association property="dept" javaType="Dept">
        <id property="did" column="did"></id>
        <result property="deptName" column="dept_name"></result>
    </association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid") Integer eid);-->
<select id="getEmpAndDept" resultMap="EmpAndDeptResultMapTwo">
    select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>

3>分步查询处理多对一的关系

此方法同样需要用到association标签,但是比方法2稍微麻烦一点,但有以下好处:

  • 可以实现延迟加载。但是必须在核心配置文件中设置全局配置
  • 代码可读性提高。
  • 可以少写一些代码
  1. 在DeptMapper上创建一个方法查询某个部门,并在DeptMapper.xml中配置sql语句

    /**
     * 通过分步查询查询员工及员工所对应的部门
     * 分步查询第第一步:通过did查询员工所对应的部门
     */
    public Dept getEmpAndDeptByStepOne(@Param("did") Integer did);
    
    <!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did)-->
    <select id="getEmpAndDeptByStepOne" resultType="dept">
        select * from t_dept where did = #{did}
    </select>
    
  2. 在EmpMapper上创建一个方法查询员工信息,并在EmpMapper.xml中配置sql语句

    /**
     * 通过分步查询查询员工及员工所对应的部门
     * 分步查询第二步:查询员工
     */
    public Emp getEmpAndDeptByStepTwo(@Param("eid") Integer eid);
    
    <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid)-->
    <select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepResultMap">
        select * from t_emp where eid = #{eid}
    </select>
    

    **注意:**该select标签中需要用resultMap属性引用配置好的EmpAndDeptByStepResultMap。

  3. 配置EmpAndDeptByStepResultMap

    <resultMap id="EmpAndDeptByStepResultMap" type="emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
        <!--
            select:设置分步查询的sql唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
            column:设置分步查询的条件
        -->
        <association property="dept"
                     select="mybatis.mapper.DeptMapper.getEmpAndDeptByStepOne"
                     column="did">
            <id property="did" column="did"></id>
            <result property="deptName" column="dept_name"></result>
        </association>
    </resultMap>
    
  4. 在测试方法中测试(只调用getEmpAndDeptByStepTwo方法即可)

**注意:**要配置分步查询,需要配置以下两个association标签的属性:

  • select:设置分步查询的sql唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
  • column:设置分步查询的条件,也就是多对一的一

4、延迟加载

概念

也就是懒加载,一般情况下,在一个方法中有多条语句需要执行SQL语句从数据库中读取数据,虚拟机会一次性读取出来后存入内存,要查看就需要打印输出,而延迟加载就是当你需要通过打印输出访问某条SQL语句对应的查询结果时再调用该条SQL语句进行执行,并不会一次性将方法中的SQL语句全部执行,可以有效降低数据库的负担。

开启延迟加载

<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>

但有些功能不需要实现延迟加载,这时候需要找到映射文件里该功能的resultMap里的association标签中设置延迟加载不对该功能生效,如下

<association property="dept"
             select="mybatis.mapper.DeptMapper.getEmpAndDeptByStepOne"
             column="did"
             fetchType="lazy">
    <id property="did" column="did"></id>
    <result property="deptName" column="dept_name"></result>
</association>

就是fetchType属性中的两个值eager和lazy

  • eager:立即加载
  • lazy:延迟加载

5、一对多映射处理

在Dept实体类中加入一个员工列表

public class Dept {
    private Integer did;

    private String deptName;

    private List<Emp> emps;
	
	//构造器,get,set,toString
}

MyBatis处理一对多的映射关系,有两种方法

1>通过collection标签处理一对多的关系

collection标签与association标签的使用类似,只不过javaType属性换成了ofType属性

/**
 * 获取部门以及部门中作用的员工信息
 */
public Dept getDeptAndEmp(@Param("did") Integer did);
<resultMap id="DeptAndEmpResultMap" type="dept">
    <id property="did" column="did"></id>
    <result property="deptName" column="dept_name"></result>
    <collection property="emps" ofType="emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
    </collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") String did)-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
    select * from t_dept left join t_emp on t_dept.did = t_emp.did where  t_dept.did = #{did}
</select>

**注意:**ofType属性表示的是该集合中存储的数据类型

2>分步查询处理一对多的关系

  1. 在EmpMapper上创建一个方法查询某个部门对应的员工信息,并在EmpMapper.xml中配置sql语句

    /**
     * 通过分步查询查询部门部门中对应的员工信息
     * 分步查询第一步:查询员工
     */
    public List<Emp> getDeptAndEmpByStepOne(@Param("did") Integer did);
    
    <!--List<Emp> getDeptAndEmpByStepOne(@Param("did") Integer did)-->
    <select id="getDeptAndEmpByStepOne" resultType="emp">
        select * from t_emp where did = #{did}
    </select>
    
  2. 在DeptMapper上创建一个方法查询部门信息,并在DeptMapper.xml中配置sql语句

    /**
     * 通过分步查询查询部门以及部门中对应的员工信息
     * 分步查询第二步:查询部门信息
     */
    public Dept getDeptAndEmpByStepTwo(@Param("did") Integer did);
    
    <!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did)-->
    <select id="getDeptAndEmpByStepTwo" resultMap="DeptAndEmpByStepResultMap">
        select * from t_dept where did = #{did}
    </select>
    

    **注意:**该select标签中需要用resultMap属性引用配置好的DeptAndEmpByStepResultMap。

  3. 配置DeptAndEmpByStepResultMap

    <resultMap id="DeptAndEmpByStepResultMap" type="dept">
        <id property="did" column="did"></id>
        <result property="deptName" column="dept_name"></result>
        <!--
            select:设置分步查询的sql唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
            column:设置分步查询的条件
        -->
        <collection property="emps"
                    select="mybatis.mapper.EmpMapper.getDeptAndEmpByStepOne"
                    column="did"
                    fetchType="lazy">
            <id property="eid" column="eid"></id>
            <result property="empName" column="emp_name"></result>
            <result property="age" column="age"></result>
            <result property="sex" column="sex"></result>
            <result property="email" column="email"></result>
        </collection>
    </resultMap>
    

    **注意:**由于这里查询的员工信息用到的是did而不是eid,所以这里collection标签中的column属性值为did。

  4. 在测试方法中测试(只调用getDeptAndEmpByStepTwo方法即可)

**注意:**要配置分步查询解决一对多的映射,需要配置以下两个collection标签的属性:

  • select:设置分步查询的sql唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
  • column:设置分步查询的条件,也就是多对一的一
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值