一对多,多对一的关系

Dept与Emp多表连接

一、项目概述

本项目实现了部门(Dept)和员工(Emp)之间的多表连接查询,通过MyBatis框架实现一对多和多对一的关系映射。

1 关系说明

  • 一对多:一个部门有多个员工(Dept → Emp)
  • 多对一:多个员工属于一个部门(Emp → Dept)

二、实体类设计

2.1 Dept.java(部门实体类)

package cn.wolfcode.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Long deptno;        // 部门编号
    private String dname;       // 部门名称
    private String loc;         // 部门位置
    private List<Emp> empList;  // 一对多:一个部门有多个员工
}

2.2 Emp.java(员工实体类)

package cn.wolfcode.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Long empno;         // 员工编号
    private String ename;       // 员工姓名
    private String job;         // 员工职位
    private Long mgr;           // 上级编号
    private LocalDate hiredate;  // 入职日期
    private Double sal;         // 工资
    private Double comm;        // 奖金
    private Long deptno;       // 部门编号
    private Dept dept;          // 多对一:一个员工属于一个部门
}

三、MyBatis配置详解

3 DeptMapper.xml(核心映射文件)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.wolfcode.mapper.DeptMapper">

    <!-- 步骤1:定义结果映射 -->
    <resultMap id="deptMap" type="Dept">
        <!-- 部门主键映射 -->
        <id column="dept_deptno" property="deptno" />
        <!-- 部门基本属性映射 -->
        <result column="dname" property="dname"/>
        <result column="loc" property="loc"/>
        <!-- 步骤2:一对多关联映射 -->
        <collection property="empList" ofType="cn.wolfcode.domain.Emp">
            <!-- 员工主键映射 -->
            <id column="empno" property="empno"/>
            <!-- 员工基本属性映射 -->
            <result column="ename" property="ename"/>
            <result column="job" property="job"/>
            <result column="mgr" property="mgr"/>
            <result column="hiredate" property="hiredate"/>
            <result column="sal" property="sal"/>
            <result column="comm" property="comm"/>
            <result column="emp_deptno" property="deptno"/>
        </collection>
    </resultMap>

    <!-- 步骤3:定义SQL片段(可复用) -->
    <sql id="deptColumns">
        dept.deptno as dept_deptno, dname, loc,
        empno, ename, job, mgr, hiredate, sal, comm,
        emp.deptno as emp_deptno
    </sql>

    <!-- 步骤4:编写多表连接查询 -->
    <select id="findAll" resultMap="deptMap">
        select <include refid="deptColumns"/>
        from dept left join emp on dept.deptno=emp.deptno
    </select>
</mapper>

SQL查询详解

select
    dept.deptno as dept_deptno,  -- 部门编号(带别名避免冲突)
    dname,                       -- 部门名称
    loc,                         -- 部门位置
    empno,                       -- 员工编号
    ename,                       -- 员工姓名
    job,                         -- 员工职位
    mgr,                         -- 上级编号
    hiredate,                    -- 入职日期
    sal,                         -- 工资
    comm,                        -- 奖金
    emp.deptno as emp_deptno      -- 员工的部门编号(带别名)
from dept
left join emp on dept.deptno=emp.deptno  -- 左连接,确保没有员工的部门也能查到

关键点说明

  • left join:左连接,确保即使部门没有员工也能查询到该部门
  • as dept_deptno:为dept表的deptno列添加别名,避免与emp表的deptno冲突
  • as emp_deptno:为emp表的deptno列添加别名,避免与dept表的deptno冲突

四、执行流程详解

步骤1:测试方法调用

@Test
public void test2() throws IOException {
    List<Dept> deptList = deptMapper.findAll();
    deptList.stream().forEach(System.out::println);
}

步骤2:Mapper实现类执行

public class DeptMapperImpl implements DeptMapper {
    @Override
    public List<Dept> findAll() {
        // 获取SqlSession
        SqlSession sqlSession = MyBatisTool.getSqlSession();
        try {
            // 调用映射接口方法
            List<Dept> deptList = sqlSession.getMapper(DeptMapper.class).findAll();
            return deptList;
        } finally {
            // 关闭SqlSession
            MyBatisTool.close(sqlSession);
        }
    }
}

步骤3:MyBatis工具类创建SqlSession

public class MyBatisTool {
    public static SqlSession getSqlSession() {
        try (InputStream is = Resources.getResourceAsStream("mybatis-config.xml")) {
            // 创建SqlSessionFactory
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            // 创建SqlSession
            return factory.openSession();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

步骤4:MyBatis执行SQL查询

1. 加载mybatis-config.xml配置文件
2. 加载DeptMapper.xml映射文件
3. 根据方法名findAll找到对应的SQL语句
4. 执行SQL:select ... from dept left join emp on dept.deptno=emp.deptno
5. 获取数据库查询结果集

步骤5:MyBatis结果映射

对于查询结果中的每一行数据:
1. 读取dept_deptno列,创建或获取对应的Dept对象
2. 读取dname和loc列,设置到Dept对象
3. 读取empno列,创建Emp对象
4. 读取员工相关列,设置到Emp对象
5. 将Emp对象添加到Dept对象的empList中
6. 重复直到处理完所有行

步骤6:返回结果

返回List<Dept>,每个Dept对象包含:
- deptno: 部门编号
- dname: 部门名称
- loc: 部门位置
- empList: 该部门的所有员工列表

posted on 2026-01-28 19:43  LVjiani  阅读(8)  评论(0)    收藏  举报

导航