MyBatis 从入门到实战(二):代理 Dao 开发与多表关联查询

在 MyBatis 入门阶段,我们通常使用原生 Dao 方式编写数据访问层。但在实际企业开发中,更简洁、更规范的代理 Dao(Mapper 接口代理) 才是主流方案。它不需要我们手动实现 Dao 实现类,只需要定义接口与 XML 映射文件,由 MyBatis 自动生成代理对象完成数据库操作。

二、环境准备与实体类设计

本次案例以经典的 部门(Dept)- 员工(Emp) 模型为例:

1. 数据库表结构

  • 部门表 deptdid(主键)、dname
  • 员工表 empeid(主键)、enamesalarydno(外键,关联部门主键)

2. 实体类设计

Dept 实体类(一的一方)

java 复制代码
public class Dept {
    private Integer did;
    private String dname;

    // 一对多:一个部门包含多个员工
    private List<Emp> emp4;

    // 无参/有参构造、get/set、toString
}

Emp 实体类(多的一方)

java 复制代码
public class Emp {
    private Integer eid;
    private String ename;
    private Integer salary;
    private Integer dno;

    // 多对一:一个员工属于一个部门
    private Dept dept;

    // 无参/有参构造、get/set、toString
}

口诀:一对多加集合,多对一加对象。

三、代理 Dao 方式开发 CRUD

MyBatis 代理 Dao 开发遵循几个固定规则:

  1. Mapper 接口全类名与 XML 映射文件 namespace 一致
  2. 接口方法名与 XML 中 statement id 一致
  3. 方法入参与 parameterType 一致
  4. 方法返回值与 resultType/resultMap 一致

1. Mapper 接口定义

java 复制代码
public interface DeptMapper {
    List<Dept> selectAll();
}

public interface EmpMapper {
    Emp selectEmpById(Integer eid);
}

2. XML 映射文件

XML 复制代码
<!-- DeptMapper.xml -->
<mapper namespace="com.xxx.mapper.DeptMapper">
    <select id="selectAll" resultType="Dept">
        select * from dept
    </select>
</mapper>

3. 测试类

java 复制代码
@Test
public void testSelectAll() {
    SqlSession session = MyBatisUtil.getSession();
    DeptMapper mapper = session.getMapper(DeptMapper.class);
    List<Dept> deptList = mapper.selectAll();
    deptList.forEach(System.out::println);
    session.close();
}

到目前为止,基础 CRUD 可以完成。但当我们需要查询部门及其下属员工查询员工及其所属部门时,简单的 resultType 已经无法满足封装需求。

四、多表关联查询

1. 一对多查询:查询部门及其下属员工

需求:查询所有部门,并展示每个部门下的所有员工。

  • 一的一方:Dept
  • 多的一方:Emp
  • 封装方式:List<Emp>
  • XML 标签:<collection>
resultMap 配置
XML 复制代码
<resultMap id="DeptEmpMap" type="Dept">
    <id column="did" property="did"/>
    <result column="dname" property="dname"/>

    <!-- 一对多:集合映射 -->
    <collection property="emp4" ofType="Emp">
        <result column="ename" property="ename"/>
    </collection>
</resultMap>

<select id="selectAllDeptAndEmp" resultMap="DeptEmpMap">
    select d.did, d.dname, e.ename
    from dept d
    left join emp e on d.did = e.dno
</select>

2. 多对一查询:查询员工及其所属部门

需求:查询某个员工,以及他所属的部门信息。

  • 以 emp 为主表
  • 多对一使用 <association> 标签
  • 映射单个对象,使用 javaType
resultMap 配置
XML 复制代码
<resultMap id="EmpDeptMap" type="Emp">
    <id column="eid" property="eid"/>
    <result column="ename" property="ename"/>

    <!-- 多对一:单个对象映射 -->
    <association property="dept" javaType="Dept">
        <result column="dname" property="dname"/>
    </association>
</resultMap>

<select id="selectEmpWithDeptById" parameterType="int" resultMap="EmpDeptMap">
    select e.eid, e.ename, d.dname
    from emp e
    left join dept d on e.dno = d.did
    where e.eid = #{eid}
</select>

3. 连表 SQL 说明

sql 复制代码
SELECT e.eid, e.ename, d.did, d.dname
FROM emp e
LEFT JOIN dept d ON e.dno = d.did
WHERE e.eid = 1;
  • emp edept d 是表别名,用于区分字段、简化书写
  • 多表查询必须明确关联条件:主表主键 = 从表外键

五、总结

  1. 开发优先使用 Mapper 代理 Dao 方式,省略 Dao 实现类
  2. 单表查询用 resultType,多表关联 / 嵌套对象必须用 resultMap
  3. 一对多:<collection> + ofType + List
  4. 多对一:<association> + javaType + 单个对象
  5. 连表查询遵循:左连接保证数据完整,外键关联保证关系正确
相关推荐
杨云龙UP2 分钟前
Oracle RAC / ODA 生产环境指定 PDB 启动 SOP
linux·运维·数据库·oracle
语戚5 分钟前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
kingwebo'sZone13 分钟前
在Cent上安装Mysql 8.0的遇到的问题和解决办法
数据库·mysql·adb
幽络源小助理22 分钟前
最新知识付费系统网站源码 PC+H5双端 附安装教程 – 幽络源源码网
大数据·数据库
我命由我1234544 分钟前
Android 开发问题:MlKitException: An internal error occurred during initialization.
android·java·java-ee·android jetpack·android-studio·androidx·android runtime
小白考证进阶中1 小时前
Oracle OCP证书报考&考试全指南
数据库·oracle·oracle ocp·ocp认证·oracle认证·甲骨文认证·oracle ocp题库
星恒随风1 小时前
Python 基础语法详解(一):从表达式、变量到数据类型
开发语言·笔记·python·学习
888CC++1 小时前
java 并发编程
java·开发语言·python
罗超驿1 小时前
18.Web API 实战:元素与表单属性的获取和修改
开发语言·前端·javascript
无风听海1 小时前
JSON Web Token(JWT)完全指南
java·前端·json