• Mybatis - 一对多/多对一映射



    前言

    本文以 SpringBoot 整合 Mybatis 为例,讲解项目中一对多和多对一的简单用法

    项目结构

    在这里插入图片描述

    一、数据库表

    1. 员工表 t_emp

    在这里插入图片描述

    2. 部门表 t_dept

    在这里插入图片描述

    二、实体类

    1. Emp 员工实体类(添加多对一属性)

    @Data
    public class Emp {
    
        private Integer eId;
        private String eName;
        private Integer age;
        private String sex;
        private String phone;
        private String email;
    
        // 多对一关系 后添加的属性
        private Dept dept;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2. dept 部门实体类(添加一对多属性)

    @Data
    public class Dept {
    
        private Integer dId;
        private String dName;
        private String dLocation;
        // private Emp emp1;
        // private Emp emp2;
        // private Emp emp3;
        // ... 可能出来0 ~ ? Emp对象  一对多关系 后添加的属性
        private List<Emp> emps;
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三、配置文件,配置类

    1. 配置文件 application.properties

    # 数据库连接
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai
    # 数据库用户名
    spring.datasource.username=root
    # 数据库密码
    spring.datasource.password=root
    
    # 关联映射的配置(指定XML文件所在的位置)
    mybatis.mapper-locations=classpath:mappers/*.xml
    # 配置别名
    mybatis.type-aliases-package=com.cy.mybatis.pojo.entity
    # 开启驼峰映射 
    mybatis.configuration.map-underscore-to-camel-case=true
    
    # 日志
    logging.level.com.cy.mybatis.mapper=debug
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2. 配置类 MybatisConfig.java

    @Configuration // 将它标注的类为配置类
    @MapperScan("com.cy.mybatis.mapper")
    public class MybatisConfig {
    }
    
    • 1
    • 2
    • 3
    • 4

    四、持久层接口

    1. EmpMapper.java

    public interface EmpMapper {
    
        // 根据员工id查询员工信息(包括部门信息)
        Map<String,Object> getObjectByIdToMap(@Param("eid") int eid);
        
    	// 根据员工id查询员工信息(包括部门信息)
        Emp getEmpAndDeptById(@Param("eid") int eid);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. DeptMapper.java

    public interface DeptMapper {
        // 通过部门id查询部门所有信息(包含部门员工)
        Dept getDeptAndEmpById(@Param("did") int did);
    }
    
    • 1
    • 2
    • 3
    • 4

    五、xml映射文件

    1. EmpMapper.xml(多对一)

    1.1 级联

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.cy.mybatis.mapper.EmpMapper">
    	
    	
        <resultMap id="empAndDeptResultMap" type="emp">
            <id column="e_id" property="eId"/>
            <result column="e_name" property="eName"/>
            <result column="age" property="age"/>
            <result column="sex" property="sex"/>
            <result column="phone" property="phone"/>
            <result column="email" property="email"/>
            
            <result column="d_id" property="dept.dId"/>
            <result column="d_name" property="dept.dName">result>
            <result column="d_location" property="dept.dLocation">result>
        resultMap>
    
        <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
            select *
            from t_emp e
            join t_dept d
            on e.d_id=d.d_id
            where e.e_id = #{eid}
        select>
    
    mapper>
    
    
    • 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

    测试输出结果:
    在这里插入图片描述

    1.2 association 标签 - 关联查询(常用)

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.cy.mybatis.mapper.EmpMapper">
    	
    	<-- 通过Map封装查询结果 -->
        <select id="getObjectByIdToMap" resultType="java.util.Map">
            select *
            from t_emp e
            join t_dept d
            on e.d_id=d.d_id
            where e.e_id = #{eid}
        select>
    	
    	
        <resultMap id="empAndDeptResultMap" type="emp">
            <id column="e_id" property="eId"/>
            <result column="e_name" property="eName"/>
            <result column="age" property="age"/>
            <result column="sex" property="sex"/>
            <result column="phone" property="phone"/>
            <result column="email" property="email"/>
            
            <association property="dept" javaType="Dept">
                <id column="d_id" property="dId">id>
                <result column="d_name" property="dName">result>
                <result column="d_location" property="dLocation">result>
            association>
        resultMap>
    
        <select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
            select *
            from t_emp e
            join t_dept d
            on e.d_id=d.d_id
            where e.e_id = #{eid}
        select>
    
    mapper>
    
    
    • 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

    1.3 association 标签 - 分布查询(更常用)

    • 步骤一:EmpMapper.java

      public interface EmpMapper {
          /**
           * 通过分布查询: 查询员工以及员工所对应的部门信息
           * 分布查询第一步: 查询员工信息
           * @param eid 员工id
           * @return
           */
          Emp getEmpAndDeptByIdStepOne(@Param("eid") int eid);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 步骤二:EmpMapper.xml

      
      DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.cy.mybatis.mapper.EmpMapper">
      
          <resultMap id="EmpAndDeptByIdStepResultMap" type="emp">
              <id column="e_id" property="eId"/>
              <result column="e_name" property="eName"/>
              <result column="age" property="age"/>
              <result column="sex" property="sex"/>
              <result column="phone" property="phone"/>
              <result column="email" property="email"/>
              <--
          	 association: 处理多对一的映射关系
                 参数: property 需要处理多对一的映射关系的属性名称  Dept dept 中的dept
                       select 设置分部查询的sql语句的唯一标识(namespace.SQLId或mapper接口的全限定名.方法名)
                       column 设置分部查询的条件(第二步查询需要的条件)
      		-->
              <association property="dept"
                           select="com.cy.mybatis.mapper.DeptMapper.getEmpAndDeptByIdStepTwo"
                           column="d_id">association>
          resultMap>
      
          <select id="getEmpAndDeptByIdStepOne" resultMap="EmpAndDeptByIdStepResultMap">
              select * from t_emp where e_id = #{eid}
          select>
      mapper>    
      
      • 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
    • 步骤三:DeptMapper.java

      public interface DeptMapper {
          /**
           * 通过分布查询: 查询员工以及员工所对应的部门信息
           * 分布查询第二步: 通过did查询员工所对应的部门信息
           * @param did 部门id
           * @return
           */
          Dept getEmpAndDeptByIdStepTwo(@Param("did") int did);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 步骤四:DeptMapper.xml

      
      DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.cy.mybatis.mapper.DeptMapper">
      
          <resultMap id="DeptResultMap" type="dept">
              <id column="d_id" property="dId"/>
              <result column="d_name" property="dName"/>
              <result column="d_location" property="dLocation"/>
          resultMap>
      
          <select id="getEmpAndDeptByIdStepTwo" resultMap="DeptResultMap">
              select * from t_dept where d_id = #{did}
          select>
      mapper>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • 步骤五:测试类测试 EmpMapperTests.java

      @SpringBootTest
      public class EmpMapperTests {
      
          @Autowired
          EmpMapper empMapper;
      
          @Test
          void testGetEmpAndDeptByIdStepOne() {
              Emp emp = empMapper.getEmpAndDeptByIdStepOne(1);
              System.out.println(emp);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      测试结果:

      在这里插入图片描述
      与之前的关联查询不同,这里执行的是两条SQL语句

    2. DeptMapper.xml(一对多)

    2.1 collection 标签 - 关联查询(常用)

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.cy.mybatis.mapper.DeptMapper">
    
        
        <resultMap id="DeptAndEmpBResultMap" type="dept">
            <id column="d_id" property="dId"/>
            <result column="d_name" property="dName"/>
            <result column="d_location" property="dLocation"/>
            <collection property="emps" ofType="Emp">
                <id column="e_id" property="eId"/>
                <result column="e_name" property="eName"/>
                <result column="age" property="age"/>
                <result column="sex" property="sex"/>
                <result column="phone" property="phone"/>
                <result column="email" property="email"/>
            collection>
        resultMap>
    
        <select id="getDeptAndEmpById" resultMap="DeptAndEmpBResultMap">
            select *
            from t_emp
            join t_dept
            on t_emp.d_id=t_dept.d_id
            where t_dept.d_id = #{did}
        select>
    
    mapper>
    
    
    • 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

    2.2 collection 标签 - 分步查询(更常用)

    • 持续更新…

    六、测试类

    1. EmpMapperTests

    @SpringBootTest
    public class EmpMapperTests {
    
        @Autowired
        EmpMapper empMapper;
    
        @Test
        void testGetObjectByIdToMap() {
            Map<String, Object> map = empMapper.getObjectByIdToMap(1);
            System.out.println(map);
        }
    
        @Test
        void testGetEmpAndDeptById() {
            Emp emp = empMapper.getEmpAndDeptById(1);       
            System.out.println(emp);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出结果
    testGetObjectByIdToMap() 测试方法输出结果
    在这里插入图片描述

    testGetEmpAndDeptById() 测试方法输出结果
    在这里插入图片描述

    2. DeptMapperTests

    @SpringBootTest
    public class DeptMapperTests {
    
        @Autowired
        DeptMapper deptMapper;
    
        @Test
        void testGetDeptAndEmpById() {
            Dept dept = deptMapper.getDeptAndEmpById(1);
            System.out.println(dept);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出结果
    在这里插入图片描述


    总结

    在处理这种一对多和多对一映射关系的业务中,我们可以通过两种方式去实现:

    • 封装到 Map 容器中
    • 添加自定义映射关系 ResultMap
      • 多对一
        • 实体类
          • 在多的那个实体类中(Emp)添加一的类型的属性 (Dept dept)
        • ResultMap 结果集映射 添加 标签
          • 属性
            • property 需要处理多对一的映射关系的属性名称 如:Dept dept 中的dept
            • javaType 该属性的类型 如:Dept dept 中的Dept
      • 一对多
        • 实体类
          • 在一的那个实体类中(Emp)添加多的类型的属性的集合 (List emps)
        • ResultMap 结果集映射 添加 标签
          • 属性
            • property 需要处理一对多的映射关系的属性名称 如:List emps 中的emps
            • ofType(的类型) 该属性所对应的集合中存储的类型,集合中泛型的类型 如:List emps 中的Emp
  • 相关阅读:
    SpringMVC的架构有什么优势?——表单和数据校验(四)
    ES6初步了解生成器
    基于SpringBoot的在线学生请假管理系统的设计与实现毕业设计源码060935
    对象内存布局
    C#扩展函数&Unity子对象组件的定向获取
    对射式红外传感器模块、测速传感器模块、计数器模块、电机测试模块、槽型光耦模块
    P1941 [NOIP2014 提高组] 飞扬的小鸟
    守护进程深度分析
    IMX6ULL学习笔记(7)——通过SD卡启动U-Boot
    用DIV+CSS技术设计的西安旅游网站18页(web前端网页制作课作业)HTML+CSS旅游网站设计与实现
  • 原文地址:https://blog.csdn.net/weixin_46030002/article/details/127565851