多表联查
-
多对一/一对一关联
-
实体类设计(多的一方持有一的一方引用)
// 员工类(多的一方)
public class Emp {
private Long empno;
private String ename;
... //省略其他成员字段
private Dept dept; // 关联部门(一的一方)
}
// 部门类(一的一方)
public class Dept {
private Long id;
private String deptno;
...
}
-
两种查询实现方式
-
方式一:关联查询(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>
-
方式二:嵌套查询(分两个 SQL 语句查询)
- 获取员工表中 emp.deptno ,再通过 association 的 select 属性去调用部门的查询方法查询
- 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
- 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>
-
一对多/多对多
其核心思想与 多对一/一对一 的实现方法别无二致,只是将 association 标签改为 collection 即可,详见上述
-
核心要点
-
resultMap 是结果集,用来存储 SQL 语句查询出来的值
-
property 属性对应的是 Java 实体类中的字段名
-
column 属性是数据库中的列结果集,每个同名的列结果集有且仅有一
-
当 SQL 语句执行完毕时,会根据列结果集将值分配给 property 属性中相应的实体属性
-
left join 连表和 嵌套查询核心差异
| 查询方式 | SQL 执行次数 | 结果集数量 | 结果集归属/特点 | 同名字段冲突 |
| left join 连表 | 1 | 1 | 合并结果集,归属主表查询结果 | 必然冲突 |
| 嵌套查询 | 2(主表 + 子表) | 2 | 主、子查询各生成独立结果集,无合并 | 必然不会冲突 |
-
结果集只有一个,当重名时,会将最后一次查询出来的值给到结果集中,导致全部同名字段结果一致

浙公网安备 33010602011771号