赞
踩
在实际开发中,一个业务可能涉及到多个数据表的查询,那么多表查询就涉及连接查询(等值连接), 等值连接 表与表之间有一个外键关键
但是程序中最终获取的表封装的对象, 对象与对象之间是没有外键关系的,对象和对象之间只有依赖关系
对象之间关系主要是四种
1.一对一 关系 one2one to->Two->2
(1)一个人对应身份证id,一个QQ号对应一个QQ空间
2.一对多 关系 one2many
(1)一个部门对应多个员工
3.多对一 关系 many2one
(1)多个员工对应一个部门
4.多对多 关系 many2many
(1)多个学生对应多个老师,多个学生对应多个课程
什么关系应该从哪个对象作为中心点来看
一对多, 以one方作为中心点
多对一,以many方作为中心点来看
MyBatis框架支持多表查询封装对象之间关系
<collection> 一对多查询
<association> 多对一和一对一查询
上述两个标签都在手动映射标签 <ResultMap> 中
MyBatis 支持两种策略
1,等值连接策略
2,N+策略
多对一关系 :以员工为中心,多个员工对应一个部门(全局角度考虑)
需求:查询指定id某一个员工的信息(包含部门信息)
直接将多表进行联合查询直接把数据全部查询出来
select e.*,d.d_name from employee e left join department d
on e.dept_id = d.d_id where e.e_id = 1
1)先发送N(实际业务需求对应的SQL语句)查询出基本信息
2)再额外发送一条SQL语句查询对应的其他表的信息
先查询出员工的基本信息: N 业务上N只有一条就是 1
select * from employee where e_id = 3;
再根据员工的部门id查询出部门的信息 : +1
select * from department where d_id = 1;
以员工为中心查询部门(从全局角度)多个员工对应一个部门:多对一关系
Pojo映射关系
public class Employee {
private Integer eId;
private String eName;
//以员工为中心 :
多个员工对应一个部门,多对一关系,many2one
//员工与部门的对象关系
private Department dept;
public Integer geteId() {
return eId;
}
public void seteId(Integer eId) {
this.eId = eId;
}
public String geteName() {
return eName;
}
public void seteName(String eName) {
this.eName = eName;
}
public Employee(Integer eId, String eName) {
super();
this.eId = eId;
this.eName = eName;
}
public Employee() {
super();
}
@Override
public String toString() {
return "Employee [eId=" + eId + ", eName=" + eName + ", dept=" + dept + "]";
}
}
public class Department {
private Integer dId;
private String dName;
public Integer getdId() {
return dId;
}
public void setdId(Integer dId) {
this.dId = dId;
}
public String getdName() {
return dName;
}
public void setdName(String dName) {
this.dName = dName;
}
@Override
public String toString() {
return "Department [dId=" + dId + ", dName=" + dName + "]";
}
public Department(Integer dId, String dName) {
super();
this.dId = dId;
this.dName = dName;
}
public Department() {
super();
}
}
N+1 : N 就是当前需要查询结果对应发送的SQL语句的条数
+1 关联查询数据需要额外多发一条SQL语句才能查询出对应的结果
package com.ywq.mybatis.mapper;
import com.ywq.mybatis.pojo.Employee;
public interface Many2OneMapper {
/**
* 查询出指定员工的所有信息(包括部门信息)
* @param eId 员工id
* @return 员工对象
*/
Employee selectByPrimaryKey(Integer eId);
}
<?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">
<!-- 开启MyBatis的User表的y映射配置
<mapper namespace="">
映射文件的根元素
namespace:命名空间(映射文件的唯一名称)
值:必须对应映射接口的全限定名
全限定名 = 包名+简单名称
-->
<mapper namespace="com.ywq.mybatis.mapper.Many2OneMapper">
<!-- N+1策略 -->
<!-- N:业务SQL
根据员工的id查询出员工的基本信息
-->
<select id="selectByPrimaryKey" resultMap="emp_map">
select * from employee where e_id = #{eId}
</select>
<!-- 手动映射 -->
<resultMap type="com.ywq.mybatis.pojo.Employee" id="emp_map">
<!-- 主键列映射 -->
<id column="e_id" property="eId"/>
<!-- 非主键列映射 -->
<result column="e_name" property="eName"/>
<!-- 问题 private Department dept; 对象如何映射?
解决方案:
使用联合查询标签<association property="" column="" select=""/>
property="需要映射的属性,当前场景就是 部门对象dept"
column="能够最终映射部门对于对应的外键列,当前场景就是dept_id"
select="需要额外发送+1的查询功能id"
-->
<association property="dept" column="dept_id" select="selectDetpByPrarimKey"/>
</resultMap>
<!--
+1:联合查询功能,根据部门id查询出部门对象
-->
<select id="selectDetpByPrarimKey" parameterType="Integer" resultType="com.ywq.mybatis.pojo.Department">
select * from department where d_id = #{dId}
</select>
</mapper>
package com.ywq.mybatis.mapper;
import com.ywq.mybatis.pojo.Employee;
public interface Many2OneMapper {
/**
* 查询出指定员工的所有信息(包括部门信息)
* @param eId 员工id
* @return 员工对象
*/
Employee selectByPrimaryKey(Integer eId);
}
<?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">
<!-- 开启MyBatis的User表的y映射配置
<mapper namespace="">
映射文件的根元素
namespace:命名空间(映射文件的唯一名称)
值:必须对应映射接口的全限定名
全限定名 = 包名+简单名称
-->
<mapper namespace="com.ywq.mybatis.mapper.Many2OneMapper">
<!-- 等值连接策略:一条sql,把所有数据都查出来,开发者根据mybatis配置
mybatis底层自动将这些数据封装对应的员工和部门对象
-->
<select id="selectByPrimaryKey" resultMap="emp_map">
select * from employee e
left join department d
on e.dept_id = d.d_id where e.e_id = #{eId};
</select>
<!-- 手动映射 -->
<resultMap type="com.ywq.mybatis.pojo.Employee" id="emp_map">
<!-- 映射员工基本信息 -->
<id column="e_id" property="eId"/>
<result column="e_name" property="eName"/>
<!-- 问题
private Department dept; 如何映射?
<association property="" javaType="">
property="需要映射的属性,当前就是部门对象dept"
javaType="需要映射的属性的数据类型,当前就是部门"
在此标签内部去映射部门对象
-->
<association property="dept" javaType="com.ywq.mybatis.pojo.Department">
<id column="d_id" property="dId"/>
<result column="d_name" property="dName"/>
</association>
</resultMap>
</mapper>
以部门为中心查询部门的所有信息(包括员工),一个部门对应多个员工
Pojo映射关系
package com.ywq.mybatis.pojo;
public class Employee {
private Integer eId;
private String eName;
private Department dept;
public Integer geteId() {
return eId;
}
public void seteId(Integer eId) {
this.eId = eId;
}
public String geteName() {
return eName;
}
public void seteName(String eName) {
this.eName = eName;
}
public Employee(Integer eId, String eName) {
super();
this.eId = eId;
this.eName = eName;
}
public Employee() {
super();
}
@Override
public String toString() {
return "Employee [eId=" + eId + ", eName=" + eName + "]";
}
}
package com.ywq.mybatis.pojo;
import java.util.List;
public class Department {
private Integer dId;
private String dName;
/*
* 以部门为中心,部门维护关系,一个部门对应多个员工
*
* 此处应该使用一个集合维护部门员工管理
*
* */
private List<Employee> employees;
public Integer getdId() {
return dId;
}
public void setdId(Integer dId) {
this.dId = dId;
}
public String getdName() {
return dName;
}
public void setdName(String dName) {
this.dName = dName;
}
public Department(Integer dId, String dName) {
super();
this.dId = dId;
this.dName = dName;
}
public Department() {
super();
}
@Override
public String toString() {
return "Department [dId=" + dId + ", dName=" + dName + ", employees=" + employees + "]";
}
}
N+1 : N 就是当前需要查询结果对应发送的SQL语句的条数
+1 关联查询数据需要额外多发一条SQL语句才能查询出对应的结果
package com.ywq.mybatis.mapper;
import com.ywq.mybatis.pojo.Department;
public interface One2ManyMapper {
/**
* 查询出指定部门的所有信息(包括此部门对应的所有员工信息)
* @param dId 部门id
* @return 部门对象
*/
Department selectByPrimaryKey(Integer dId);
}
<?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">
<!-- 开启MyBatis的User表的y映射配置
<mapper namespace="">
映射文件的根元素
namespace:命名空间(映射文件的唯一名称)
值:必须对应映射接口的全限定名
全限定名 = 包名+简单名称
-->
<mapper namespace="com.ywq.mybatis.mapper.One2ManyMapper">
<!-- N+1策略 -->
<!-- N:业务SQL
根据部门的id查询出部门的基本信息
-->
<select id="selectByPrimaryKey" resultMap="dept_map">
select * from department where d_id = #{dId}
</select>
<!-- 手动映射 -->
<resultMap type="com.ywq.mybatis.pojo.Department" id="dept_map">
<id column="d_id" property="dId"/>
<result column="d_name" property="dName"/>
<!--
问题: private List<Employee> employess;集合如何映射?
解决方案: 使用集合映射标签
<collection property="" column="" select=""/>
property="需要映射属性,当前就是员工对象的集合employees"
column="映射集合需要条件,就是部门主键id:d_id(去员工表中根据部门id查询所有员工)"
-->
<collection property="employees" column="d_id" select="selectEmployeesByDeptId"/>
</resultMap>
<!--
+1 : 根据部门的id查询出所有的员工,联合查询功能
此功能返回的是一个集合,集合中封装的一个个员工对象,Employee
-->
<select id="selectEmployeesByDeptId" resultType="com.ywq.mybatis.pojo.Employee">
select * from employee where dept_id = #{d_id}
</select>
</mapper>
运行结果
package com.ywq.mybatis.mapper;
import com.ywq.mybatis.pojo.Department;
public interface One2ManyMapper {
/**
* 查询出指定部门的所有信息(包括此部门对应的所有员工信息)
* @param dId 部门id
* @return 部门对象
*/
Department selectByPrimaryKey(Integer dId);
}
<?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">
<!-- 开启MyBatis的User表的y映射配置
<mapper namespace="">
映射文件的根元素
namespace:命名空间(映射文件的唯一名称)
值:必须对应映射接口的全限定名
全限定名 = 包名+简单名称
-->
<mapper namespace="com.ywq.mybatis.mapper.One2ManyMapper">
<!--
等值连接策略:一条SQL语句将数据全部查询出来,开发者根据MyBatis的规则配置
运行过程,Mybatis自动将数据封装成对应的对象
-->
<select id="selectByPrimaryKey" resultMap="dept_map">
select * from employee e left join department d
ON e.dept_id = d.d_id where d.d_id = #{dId}
</select>
<!-- 手动映射 -->
<resultMap type="com.ywq.mybatis.pojo.Department" id="dept_map">
<id column="d_id" property="dId"/>
<result column="d_name" property="dName"/>
<!--
问题: private List<Employee> employess;集合如何映射?
解决方案: 使用集合映射标签
<collection property="" ofType=""/>
property="需要映射属性,当前就是员工对象的集合employees"
ofType="需要映射集合属性中泛型的属性类型,当前场景就是员工 :Employee"
-->
<!-- 在此标签内部从查询的数据中映射一个个员工对象 -->
<collection property="employees" ofType="com.ywq.mybatis.pojo.Employee">
<!-- 员工的主键 -->
<id column="e_id" property="eId"/>
<!-- 员工的名称 -->
<result column="e_name" property="eName"/>
</collection>
</resultMap>
</mapper>
运行结果
只会发送一条SQL语句
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。