多表联查

  1. 多对一/一对一关联

  2. 实体类设计(多的一方持有一的一方引用)

// 员工类(多的一方)
public class Emp {
  private Long empno;
  private String ename;
  ... //省略其他成员字段
  private Dept dept; // 关联部门(一的一方)
}

// 部门类(一的一方)
public class Dept {
  private Long id;
  private String deptno;
  ...
}
  1. 两种查询实现方式

  2. 方式一:关联查询(left join 一次查全数据)

  • 核心:通过 left join 关联两张表

  • 用 resultMap 标签名封装员工类中的成员字段,再用 association 封装部门对象中的成员字段

第一种:直接写出对应类中的字段名

<resultMap id="empMap" type="cn.wolfcode.domain.Emp">
    <id property="empno" column="empno"/>
    <result property="ename" column="ename"/>
    ...
    <result property="deptno" column="deptno"/>

    <result property="dept.deptno" column="deptno"/>
    <result property="dept.dname" column="dname"/>
    <result property="dept.loc" column="loc"/>
</resultMap>

第二种:

<resultMap id="empResultMap" type="cn.wolfcode.domain.Emp">
    <id property="empno" column="empno"/>
    <result property="ename" column="ename"/>
    ...
    <result property="deptno" column="deptno"/>
  <!-- 封装部门对象:javaType指定关联对象类型 -->
    <association property="dept" javaType="cn.wolfcode.domain.Dept">-->
        <id property="deptno" column="deptno"/>
        <result property="dname" column="dname"/>
        <result property="loc" column="loc"/>
    </association>
</resultMap>

<!-- sql 字段的预编写,通过下面的 include 标签来使用 -->
<sql id="emp_cols">
        empno,
        ename,
        ...
        emp.deptno,
        
     <!-- 部门 列-->
        dept.deptno,
        dname,
        loc
</sql>
    
<select id="selOneById" resultMap="empResultMap">
  select 
  <include refid="emp_cols"/>
  from emp left join dept on emp.depton = dept.depton
</select>

第三种:通过 resultMap 属性引入 DeptMappr.xml 的命名空间中的 resultMap 的 id 属性


<resultMap id="empResultMap" type="cn.wolfcode.domain.Emp">
    <id property="empno" column="empno"/>
    <result property="ename" column="ename"/>
    ....
    <result property="deptno" column="deptno"/>
  <!-- 封装部门对象:javaType指定关联对象类型 -->
    <association property="dept" javaType="cn.wolfcode.domain.Dept" 
          resultMap="cn.wolfcode.mapper.DeptMapper.deptMap"/>
</resultMap>

<!-- 对应的 Dept 中的 XML 文件的配置信息 -->
<mapper namespace="cn.wolfcode.mapper.DeptMapper">
<resultMap id="deptMap" type="Dept">
        <id property="deptno" column="dno"/>
        <result property="dname" column="dname"/>
        <result property="loc" column="loc"/>
</resultMap>

<!-- sql 字段的预编写,通过下面的 include 标签来使用 -->
<sql id="emp_cols">
        empno,
        ename,
        ...
        emp.deptno,
        
     <!-- 部门 列-->
        dept.deptno,
        dname,
        loc
</sql>
    
<select id="selOneById" resultMap="empResultMap">
  select 
  <include refid="emp_cols"/>
  from emp left join dept on emp.depton = dept.depton
</select>
  1. 方式二:嵌套查询(分两个 SQL 语句查询)

  • 获取员工表中 emp.deptno ,再通过 association 的 select 属性去调用部门的查询方法查询
  1. EmpMapper.XML 配置信息
<resultMap id="empResultMap" type="cn.wolfcode.domain.Emp">
    <id property="empno" column="empno"/>
    <result property="ename" column="ename"/>
    ......
    <result property="deptno" column="deptno"/>
    
  <!-- 封装部门对象:javaType指定关联对象类型 -->
    <association property="dept" column="dept_id"
        select="cn.wolfcode.mapper.DeptMapper.selById"
        javaType="cn.wolfcode.domain.Dept"/>
</resultMap>

<sql id="emp_cols">
        empno,
        ename,
        ...
        emp.deptno
</sql>
    
    
<select id="selOneById" resultMap="empResultMap">
  select 
  <include refid="emp_cols"/>
  from emp 
</select>

column:表示传递给部门查询的参数,对应的是数据库中的列名(不能使用emp.dept 在数据库中不属于列名)

select:表示部门查询的方法id

  1. DeptMapper.XML 配置信息
<mapper namespace="cn.wolfcode.mapper.DeptMapper">

<sql id="dept_cols">
    deptno,
    dname,
    loc
</sql>

<!-- 调用该 SQL 语句嵌套在原 SQL 语句中-->
<select id="selById" resultType="cn.wolfcode.domain.Dept">
    select 
    <include refid="dept_cols"/>
    from dept
    where deptno = #{deptno}
</select>
  1. 一对多/多对多

其核心思想与 多对一/一对一 的实现方法别无二致,只是将 association 标签改为 collection 即可,详见上述

  1. 核心要点

  2. resultMap 是结果集,用来存储 SQL 语句查询出来的值

  3. property 属性对应的是 Java 实体类中的字段名

  4. column 属性是数据库中的列结果集,每个同名的列结果集有且仅有一

  5. 当 SQL 语句执行完毕时,会根据列结果集将值分配给 property 属性中相应的实体属性

  6. left join 连表和 嵌套查询核心差异

查询方式 SQL 执行次数 结果集数量 结果集归属/特点 同名字段冲突
left join 连表 1 1 合并结果集,归属主表查询结果 必然冲突
嵌套查询 2(主表 + 子表) 2 主、子查询各生成独立结果集,无合并 必然不会冲突
  1. 结果集只有一个,当重名时,会将最后一次查询出来的值给到结果集中,导致全部同名字段结果一致

posted @ 2026-01-28 22:29  北海道第一原神高手  阅读(20)  评论(0)    收藏  举报