• Mybatis:自定义映射resultMap(7)


    Mybaits笔记框架:https://blog.csdn.net/qq_43751200/article/details/128154837
    Mybatis中文官方文档: https://mybatis.org/mybatis-3/zh/index.html

    1. Mybatis环境搭建

    创建数据库表

    -- 创建t_emp表
    create table t_emp(
    	eid int NOT NULL PRIMARY KEY, 
    	emp_name varchar(20),
    	age int,
    	sex char,
    	email varchar(20),
    	did int
    )
    
    -- 向t_emp表中插入数据
    insert into t_emp(eid, emp_name, age, sex, email, did)
    values(1, 'lsm', 23, '男', '1234@qq.com', 1),
    			(2, 'yxy', 23, '男', '1234@qq.com', 2),
    			(3, 'lxy1', 23, '男', '1234@qq.com', 3),
    			(4, 'yxy_lsm', 23, '男', '1234@qq.com', 2),
    			(5, 'lxy', 23, '男', '1234@qq.com', 1)
    
    
    -- 创建t_dept表
    create table t_dept(
    	did int,
    	dept_name varchar(20)
    )
    
    -- 向t_dept表中插入数据
    insert into t_dept(did, dept_name) values(1, 'A'),(2, 'B'),(3, 'C')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    在这里插入图片描述

    在maven项目中创建对应的实体类(Empt类 和 Dept类)
    Emp类

    package com.atguigu.pojo;
    
    /**
     * @Author Mr.Lu
     * @Date 2022/12/2 19:08
     * @ClassName Emp
     * @Version 1.0
     */
    public class Emp {
        private Integer eid;
        // t_emp表该列名为emp_name
        private String empName;
        private  Integer age;
        private String sex;
        private String email;
    
        public Emp() {
        }
    
        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 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 + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    Dept类

    package com.atguigu.pojo;
    
    /**
     * @Author Mr.Lu
     * @Date 2022/12/2 19:07
     * @ClassName Dept
     * @Version 1.0
     */
    public class Dept {
        private Integer did;
        // t_dept表该列名为dept_name
        private String deptName;
    
        public Dept() {
        }
    
        public Dept(Integer did, String deptName) {
            this.did = did;
            this.deptName = deptName;
        }
    
        public Integer getDid() {
            return did;
        }
    
        public void setDid(Integer did) {
            this.did = did;
        }
    
        public String getDeptName() {
            return deptName;
        }
    
        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }
    
        @Override
        public String toString() {
            return "Dept{" +
                    "did=" + did +
                    ", deptName='" + deptName + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    项目结构

    在这里插入图片描述

    2. 问题引入

    DeptMapper接口

       /**
         * 获取表t_Emp的所有信息
         * @return
         */
        List<Emp> getEmpAll();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    DeptMapper接口对应的DeptMapper.xml配置文件

        <!--List<Emp> getEmpAll();-->
        <select id="getEmpAll" resultType="Emp">
            select * from t_emp
        </select>
    
    • 1
    • 2
    • 3
    • 4

    测试方法

     @Test
        public void testGetEmpAll(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            List<Emp> empAll = empMapper.getEmpAll();
            for(Emp emp : empAll){
                System.out.println(emp);
            }
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    问题描述:经过上图发现empName对应的值都为null,但是t_emp表中的emp_name是存在值的,这是为什么呐?。经过分析产生这种情况的原因在于表中的字段名和对应类的属性名不一致,这个要如何解决呐?

    3. 解决表中的字段名和对应类的属性名不一致问题

    方式一: 为字段起别名,保持和属性名的一致

    在EmpMapper.xml中为字段起别名

        
        <select id="getEmpAll" resultType="Emp">
            select eid, emp_name empName, age, sex, email from t_emp
        select>
    
    • 1
    • 2
    • 3
    • 4

    测试方法测试:

    在这里插入图片描述

    方式二:设置全局配置,将下划线_自动映射为驼峰

    可以在MyBatis的核心配置文件中的setting标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。

    在mybatis-config.xml核心配置文件中加入对应的setting标签

        
        <settings>
            
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试方法测试:

    在这里插入图片描述

    方式三:通过resultMap设置自定义的映射关系

    • resultMap:设置自定义映射

    • 属性:

      • id:表示自定义映射的唯一标识,不能重复

      • type:查询的数据要映射的实体类的类型, 例如User、Emp等实体类型

      • 子标签:

        • id:设置主键的映射关系

        • result:设置普通字段的映射关系

        • 子标签属性:

        • property:设置映射关系中实体类中的属性名

        • column:设置映射关系中表中的字段名

    • 若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来

        
        <resultMap id="empResultMap" type="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <result property="email" column="email"/>
        resultMap>
    
        <select id="getEmpAll" resultMap="empResultMap">
            select * from t_emp
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试方法测试:

    在这里插入图片描述

    4. 多对一映射处理

    多个员工对应一个部门:多对一

    一个部门对应多个员工:一对多

    需求:查询员工信息以及员工所对应的部门信息

    public class Emp {  
    	private Integer eid;  
    	private String empName;  
    	private Integer age;  
    	private String sex;  
    	private String email;  
    	private Dept dept;  // 该员工所属的部门
    	//...构造器、get、set方法等
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方式一:级联方式处理映射关系

    EmpMapper接口

      /**
         * 根据t_emp表的eid查询emp和dept表,最后封装成Emp对象返回
         * @param eid
         * @return
         */
        Emp getEmpAndDeptById(Integer eid);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    EmpMapper接口对应的EmpMapper.xml配置文件

        
        <resultMap id="empAndDeptResultMap" type="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <result property="email" column="email"/>
            
            <result property="dept.did" column="did"/>
            <result property="dept.deptName" column="dept_name"/>
        resultMap>
    
        
        <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
            select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试方法

     @Test
        public void testGetEmpAndDeptById(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = empMapper.getEmpAndDeptById(1);
            System.out.println(emp);
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    方式二:使用association处理映射关系

    EmpMapper接口

      /**
         * 根据t_emp表的eid查询emp和dept表,最后封装成Emp对象返回
         * @param eid
         * @return
         */
        Emp getEmpAndDeptById(Integer eid);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    EmpMapper接口对应的EmpMapper.xml配置文件

         
        <resultMap id="empAndDeptResultMap" type="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <result property="email" column="email"/>
            
            <association property="dept" javaType="Dept">
                <id property="did" column="did"/>
                <result property="deptName" column="dept_name"/>
            association>
        resultMap>
    
        
        <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
            select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    测试方法

     @Test
        public void testGetEmpAndDeptById(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = empMapper.getEmpAndDeptById(3);
            System.out.println(emp);
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    方式三:分步查询

    查询员工信息

    EmpMapper接口

     /**
         * 分布查询,员工及所对应的部门信息
         * 查询员工信息
         * @param eid
         * @return
         */
        Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    EmpMapper接口对应的EmpMapper.xml配置文件

    • select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
    • column:设置分步查询的条件
     <resultMap id="getEmpAndDeptByStepOneResultMap" type="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="sex" column="sex"/>
            <result property="email" column="email"/>
            
            <association property="dept"
                         select="com.atguigu.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                         column="did"/>
        resultMap>
    
        
        <select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepOneResultMap">
            select * from t_emp where eid = #{eid}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    查询部门信息

    DeptMapper接口

     /**
         * 根据did查询部门信息
         * @param did
         * @return
         */
        Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    DeptMapper接口对应的DeptMapper.xml配置文件

    
        <resultMap id="getEmpAndDeptByStepTwoResultMap" type="Dept">
            <id property="did" column="did"/>
            <result property="deptName" column="dept_name"/>
        resultMap>
    
        
        <select id="getEmpAndDeptByStepTwo" resultMap="getEmpAndDeptByStepTwoResultMap">
            select * from t_dept where did = #{did}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试方法

        @Test
        public void testGetEmpAndDeptByStepTwoAndOne(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = empMapper.getEmpAndDeptByStepOne(4);
            System.out.println(emp);
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    5. 一对多映射处理

    多个员工对应一个部门:多对一

    一个部门对应多个员工:一对多

    Dept类

    public class Dept {
        private Integer did;
        private String deptName;
        private List<Emp> empList;  // 多对一:使用集合的形式
    	//...构造器、get、set方法等
    	// 注意要重写toString方式
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    方式一:使用collection处理映射关系

    DeptMapper接口

        /**
         * 根据did查询部门信息以及其所包含的员工信息
         * @param did
         * @return
         */
        Dept getDeptAndEmp(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    DeptMapper接口对应的DeptMapper.xml配置文件

      
        
        <resultMap id="getDeptAndEmpResultMap" type="Dept">
            <id property="did" column="did"/>
            <result property="deptName" column="dept_name"/>
            
            <collection property="empList" ofType="Emp">
                <id property="eid" column="eid"/>
                <result property="empName" column="emp_name"/>
                <result property="age" column="age"/>
                <result property="sex" column="sex"/>
                <result property="email" column="email"/>
            collection>
        resultMap>
    
        <select id="getDeptAndEmp" resultMap="getDeptAndEmpResultMap">
            select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    测试方法

        @Test
        public void testGetDeptAndEmp(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
            Dept dept = deptMapper.getDeptAndEmp(1);
            System.out.println(dept);
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    方式二:分布查询

    查询部分信息

    DeptMapper接口

     /**
         * 根据部分的did查询属于该部分的所有员工信息
         * @param did
         * @return
         */
        Dept getDeptAndEmpOne(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    DeptMapper接口对应的DeptMapper.xml配置文件

    
        
        <resultMap id="getDeptAndEmpOneResultMap" type="Dept">
            <id property="did" column="did"/>
            <result property="deptName" column="dept_name"/>
            <collection property="empList"
                        select="com.atguigu.mapper.EmpMapper.getDeptAndEmpTwo"
                        column="did"/>
        resultMap>
    
        <select id="getDeptAndEmpOne" resultMap="getDeptAndEmpOneResultMap">
            select * from t_dept where t_dept.did = #{did}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    查询员工信息

    EmpMapper接口

     /**
         * 根据did查询员工集合
         * @param did
         * @return
         */
        List<Emp> getDeptAndEmpTwo(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    EmpMapper接口对应的EmpMapper.xml配置文件

     <!--List<Emp> getDeptAndEmpTwo(@Param("did") Integer did);-->
        <resultMap id="getDeptAndEmpTwoResultMap" type="Emp">
            <id property="eid" column="eid"/>
            <result property="empName" column="emp_name"/>
            <result property="age" column="age"/>
            <result property="email" column="email"/>
            <result property="sex" column="sex"/>
        </resultMap>
    
        <select id="getDeptAndEmpTwo" resultMap="getDeptAndEmpTwoResultMap">
            select * from t_emp where t_emp.did = #{did}
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    测试方法

    @Test
        public void testGetDeptAndEmpOne(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
            Dept dept = deptMapper.getDeptAndEmpOne(1);
            System.out.println(dept);
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    6.延迟加载

    • 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
    • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
      • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
    • 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”
    <settings>
    	
    	<setting name="lazyLoadingEnabled" value="true"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    @Test
        public void testGetEmpAndDeptByStepTwoAndOne(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = empMapper.getEmpAndDeptByStepOne(4);
            System.out.println(emp.getEmpName());
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 关闭延迟加载,两条SQL语句都运行了
      在这里插入图片描述

    • 开启延迟加载,只运行获取emp的SQL语句
      在这里插入图片描述

        @Test
        public void testGetEmpAndDeptByStepTwoAndOne(){
            SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = empMapper.getEmpAndDeptByStepOne(4);
            System.out.println(emp.getEmpName());
            System.out.println("===============================");
            System.out.println(emp.getDept());
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 开启后,需要用到查询dept的时候才会调用相应的SQL语句
      在这里插入图片描述

    • fetchType当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”

    <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>
    	<association property="dept"
    				 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
    				 column="did"
    				 fetchType="lazy">association>
    resultMap>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    【数据结构】C++代码定义了一个动态数组(Vector)的数据结构,并实现了一些基本的操作,包括插入、删除、扩容和输出。
    Day14 03-Shell函数定义及应用
    Photoshop (PS)下载安装
    使用platformio+arduino开发自定义板子STM32G070
    ROS三种通信方式之参数通信
    FedEx联邦快递查询寄件电子面单API接口接入教程-快递100API(以国际电子面单接口为例)
    记一次解决关机蓝屏 | MULTIPLE_IRP_COMPLETE_REQUESTS | klflt.sys
    EIA/TIA 561 Pin Layout and RS-232 pin assignments
    spring boot 配置加载顺序
    C语言入门log03
  • 原文地址:https://blog.csdn.net/qq_43751200/article/details/128154267