JAVA--多表连接(部门与员工)

部门与员工多表连接

一、多表连接的基本概念

什么是多表连接?

  • 部门表:记录公司的各个部门(财务部、研发部等)
  • 员工表:记录公司的所有员工

这两个表格通过部门编号关联起来--每个员工都属于某个部门,每个部门都有多个员工。

多表连接就是把这两个表格的数据关联起来,让我们能一起查看部门和员工的信息,就像把相关的信息粘在一起一样。

二、实体关系设计

一对多关系

关系说明:一个部门可以有多个员工

在代码中,会在部门对象里放一个员工列表,用来装这个部门的所有员工。

多对一关系

关系说明:多个员工属于一个部门

在代码中,会在每个员工对象里放一个部门对象,用来表示这个员工属于哪个部门。

三、多表连接的实现方式

方式一:分步查询(嵌套查询)

查询流程

  1. 第一步:先查询部门信息

    • 执行 SQL:select deptno,dname,loc from dept where deptno=#{deptno}
    • 得到部门的基本信息
  2. 第二步:查询这个部门的所有员工

    • 执行 SQL:根据员工的 deptno 字段查询
    • 得到这个部门的所有员工
  3. 第三步:组装数据

    • 把查到的员工放进部门的员工列表里
    • 最终得到一个包含所有员工的部门对象

方式二:一次查询(连接查询)

查询流程

  1. 一步到位:一次执行连接查询

    • 执行 SQL:select dept.deptno as dno, dname,loc,empno,ename,job,mgr,hiredate,sal,comm,emp.deptno from dept left join emp on dept.deptno=emp.deptno
    • 这个 SQL 会同时查询部门和员工的所有信息
  2. 自动组装:MyBatis 自动处理结果

    • MyBatis 会把查询结果自动分成部门和员工两部分
    • 然后把员工放进部门的员工列表里

拓展

1. INNER JOIN(内连接)

作用:只查询有员工的部门,只查询有部门的员工

通俗解释

  • 只显示两个表都有匹配数据的记录
  • 相当于两个表的交集
  • 没有员工的部门不会显示
  • 没有部门的员工也不会显示

例子

  • 财务部有员工,会显示
  • 销售部没有员工,不会显示
  • 临时工没有部门,不会显示

2. RIGHT JOIN(右连接)

作用:查询所有员工,即使这个员工没有部门

通俗解释

  • 以员工表为基础(右表),去匹配部门表(左表)
  • 不管员工有没有部门,都会显示员工信息
  • 没有部门的员工,部门相关的字段会显示为 NULL

例子

  • 有部门的员工会显示
  • 临时工没有部门,也会显示(部门信息为 NULL)

四、三种连接的区别与使用场景

连接类型对比

左连接(LEFT JOIN)

  • 核心特点:以左表为基础,查询所有左表数据
  • 结果特点:左表数据完整,右表可能有NULL
  • 适用场景:查询所有部门,即使无员工

内连接(INNER JOIN)

  • 核心特点:只查询两表匹配的数据
  • 结果特点:只显示匹配数据,无NULL
  • 适用场景:只查询有员工的部门

右连接(RIGHT JOIN)

  • 核心特点:以右表为基础,查询所有右表数据
  • 结果特点:右表数据完整,左表可能有NULL
  • 适用场景:查询所有员工,即使无部门

什么时候使用什么连接

选择左连接的情况

  • 需要保证左表数据的完整性
  • 想查看所有部门,包括暂时没有员工的部门
  • 业务逻辑以左表为主,右表为辅助信息

选择内连接的情况

  • 只关心两表都有对应数据的记录
  • 想过滤掉没有员工的部门和没有部门的员工
  • 业务逻辑要求数据必须在两边都存在

选择右连接的情况

  • 需要保证右表数据的完整性
  • 想查看所有员工,包括暂时没有部门的员工
  • 业务逻辑以右表为主,左表为辅助信息

结合实际举例

部门管理系统:通常使用左连接,因为部门是基础,即使没有员工也需要管理

员工查询系统:可以使用右连接,确保所有员工都能被查询到

报表统计系统:根据具体需求选择,需要完整数据用左/右连接,需要准确数据用内连接

五、多表连接的实际应用

1. 部门查询实现(DeptMapper.xml)

核心实现

  • 使用LEFT JOINfrom dept left join emp on dept.deptno=emp.deptno
  • SQL片段复用:使用<include refid="empColumns"/>引入预定义的字段列表
  • 字段定义:在empColumns片段中定义了所有需要查询的字段,包括部门和员工的字段
  • 结果处理:通过resultType="en.wolfcode.domain.Dept"指定返回类型

查询流程

  1. 执行连接查询:一次执行LEFT JOIN,同时获取部门和员工信息
  2. 字段映射:MyBatis根据字段名自动映射到实体类属性
  3. 数据组装:由于使用了LEFT JOIN,即使部门没有员工也会显示

五、多表连接的实际应用

1. 部门查询实现(DeptMapper.xml)

核心实现

  • 使用LEFT JOINfrom dept left join emp on dept.deptno=emp.deptno
  • SQL片段复用:使用<include refid="empColumns"/>引入预定义的字段列表
  • 字段定义:在empColumns片段中定义了所有需要查询的字段,包括部门和员工的字段
  • 结果处理:通过resultType="en.wolfcode.domain.Dept"指定返回类型

查询流程

  1. 执行连接查询:一次执行LEFT JOIN,同时获取部门和员工信息
  2. 字段映射:MyBatis根据字段名自动映射到实体类属性
  3. 数据组装:由于使用了LEFT JOIN,即使部门没有员工也会显示

需理解

1. LEFT JOIN的应用

选择原因

  • 完整性:保证左表数据的完整性
  • 灵活性:即使没有关联数据也能显示
  • 符合业务:部门是基础数据,即使暂时没有员工也需要管理

实际效果

  • 查询所有部门,包括没有员工的部门
  • 查询所有员工,包括没有部门的员工

2. 结果映射配置

你的实现

  • 部门映射:在deptMap中使用collection标签处理一对多关系
  • 员工映射:在empMap中使用association标签处理多对一关系
  • 自动映射:通过resultType直接指定返回类型,MyBatis自动处理映射

实际应用中的注意事项

  1. 字段名冲突:你的实现中已经使用了别名(如dno)来避免字段名冲突
  2. 空值处理:由于使用了LEFT JOIN,需要处理可能的NULL值
  3. 数据一致性:确保部门和员工的关联关系正确维护

六、遇到的问题及解决方法

1. 关联数据不存在

问题描述:查询结果中,关联的对象为 NULL

可能原因

  • 员工的部门编号为 NULL
  • 部门不存在(被删除了)
  • 映射配置错误

解决方法

(1). 检查员工的部门编号是否正确

检查步骤

  1. 数据库检查

    • 在数据库中执行 SQL:SELECT * FROM emp WHERE deptno IS NULL OR deptno = ''
    • 查看结果:确认是否有员工的部门编号为 NULL 或空值
  2. 代码检查

    • 查看员工实体类:确认 deptno 字段的类型和默认值
    • 检查员工创建/更新代码:确保正确设置了部门编号
  3. 数据验证

    • 添加数据验证:在员工保存前检查部门编号是否有效

(2). 检查部门是否存在

检查步骤

  1. 数据库检查

    • 在数据库中执行 SQL:SELECT * FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept)
    • 查看结果:确认是否有员工引用了不存在的部门
  2. 数据修复

    • 方法一:为员工分配有效的部门编号
    • 方法二:创建缺失的部门记录
  3. 代码优化

    • 添加部门存在性检查:在设置员工部门前验证部门是否存在

(3). 检查配置是否正确

检查步骤

  1. Mapper配置检查

    • 检查 SQL 语句:确认 JOIN 条件是否正确
    • 检查字段映射:确保字段名与实体类属性名匹配
    • 检查结果映射:确认 resultMap 配置是否正确
  2. 实体类检查

    • 检查属性名:确保与数据库字段名一致
    • 检查关联关系:确认一对多和多对一关系配置正确
    • 检查 getter/setter 方法:确保属性可以正确访问
  3. 测试验证

    • 编写单元测试:测试多表连接查询功能
    • 断点调试:在关键处设置断点,检查数据传递和映射过程
posted @ 2026-01-28 17:22  犯困蛋挞别犯困  阅读(0)  评论(0)    收藏  举报