Mybatis框架(8) —— MyBatis 的对象关系映射

本文介绍了在MyBatis框架下如何进行对象关系映射,重点讨论了多对一和一对多的查询方法,包括N+1方式和等值连接查询,并提供了映射代码及运行结果分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MyBatis 的对象关系映射

在实际开发中,一个业务可能涉及到多个数据表的查询,那么多表查询就涉及连接查询(等值查询),等值查询 表与表之间有一个外键关联

但是程序中最终获取的表封装的对象,对象与对象之间是没有外键关系的,对象和对象之间只有依赖关系

对象之间的关系主要是四种

一对一 关系 one2one
一个人对应身份证id,一个QQ号对应一个QQ空间

一对多 关系 one2many
一个部门对应多个员工

多对一 关系 many2one
多个员工对应一个部门

多对多 关系 many2many
多个学生对应多个老师,多个学生对应多个课程

什么关系应该从哪个对象作为中心点来看
一对多, 以one方作为中心点

MyBatis框架支持多表查询封装对象之间关系
<collection> 一对多查询
<association>多对一和一对一查询

准备多表,表之间有外键关系(员工表和部门表)

员工表
CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `dept_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
部门表
CREATE TABLE `department` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

多对一查询

Employee

package cn.xc.mybatis.pojo;

public class Employee {
	private Integer id;
	private String name;
	/*
	 * 员工和部门的关系 :多对一 many2one
	 * 
	 * 在员工对象中此时具体的某一个只有一个部门
	 * 
	 * 依赖管理:使用部门对象
	 * 
	 */
	private Department dept;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Department getDept() {
		return dept;
	}

	public void setDept(Department dept) {
		this.dept = dept;
	}

	public Employee(Integer id, String name, Department dept) {
		super();
		this.id = id;
		this.name = name;
		this.dept = dept;
	}

	public Employee() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", dept=" + dept + "]";
	}

}

Department

package cn.xc.mybatis.pojo;

public class Department {
	private Integer id;
	private String name;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Department() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public String toString() {
		return "Department [id=" + id + ", name=" + name + "]";
	}

	public Department(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

}

Man2oneMapper.xml 映射文件

<?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">

<mapper namespace="cn.xc.mybatis.mapper.Many2OneMapper">
	<!-- 根据员工的id查询出员工的所有信息(包括部门) -->
	<select id="selectByPrimaryKey" resultMap="emp_map">
		select id,name,dept_id from employee where id = #{id}
	</select>
	
	<!-- 手动结果集映射 -->
	<resultMap type="cn.xc.mybatis.pojo.Employee" id="emp_map">
		<id column="id" property="id"/>
		<!-- 
 			问题:private Department dept;如何映射?
 			无法使用 <id>和<result>,因为这两个标签都是值映射,无法映射对象
 			
 			解决方案:使用标签
 			<association property="" column="" select=""/>
 			property : 需要映射的对象属性,此场景就是 private Department dept;
 			column :已知可以最终得到对应对象的列,此场景就是 外键  dept_id
 			select : 调用能够返回 dept对象对应的查询功能
 				规则:命名空间 +.+功能id,如果在同一个命名空间下面可以省略 命名空间
 				此场景就是cn.xc.mybatis.mapper.Many2OneMapper.xml.selectByDeptId
 		 -->
 		 <association property="dept" column="dept_id" select="selectByDeptId"/>
	</resultMap>
	<!-- 联合查询专用功能:根据部门的id查询出部门对象 -->
	<select id="selectByDeptId" resultType="cn.xc.mybatis.pojo.Department">
		select * from department where id = #{dept_id}
	</select>
</mapper>

一对多查询

以部门为中心查询部门的所有信息(包括员工),一个部门对应多个员工
Pojo对象
Employee.java

package cn.xc.mybatis.pojo;

public class Employee {
	private Integer id;
	private String name;

	/*
	 * 员工和部门的关系 :多对一 many2one
	 * 
	 * 在员工对象中此时具体的某一个只有一个部门
	 * 
	 * 依赖管理:使用部门对象
	 * 
	 */

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Employee(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Employee() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + "]";
	}

}

Department.java

package cn.xc.mybatis.pojo;

import java.util.List;

public class Department {
	private Integer id;
	private String name;

	/*
	 * 
	 * 一个部门多个员工 : one2many
	 * 
	 * java程序一个部门对象对应多个员工对象 使用 集合 list,set
	 * 
	 */
	List<Employee> employees;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	public Department() {
		// TODO Auto-generated constructor stub
	}

	public Department(Integer id, String name, List<Employee> employees) {
		super();
		this.id = id;
		this.name = name;
		this.employees = employees;
	}

	@Override
	public String toString() {
		return "Department [id=" + id + ", name=" + name + ", employees=" + employees + "]";
	}

}

N+1方式

N+1 : N 就是当前需要查询结果对应发送的SQL语句的条数
+1 关联查询数据需要额外多发一条SQL语句才能查询出对应的结果

映射代码
<?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">

<mapper namespace="cn.xc.mybatis.mapper.One2ManyMapper">
	<!-- 根据部门的id查询出部门的所有信息 -->
	<select id="selectByPrimaryKey" resultMap="dept_id">
		select * from department where id = #{id}
	</select>
	
	<!-- 手动结果集映射 -->
	<resultMap type="cn.xc.mybatis.pojo.Department" id="dept_id">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<!-- 
 			问题:	List<Employee> employees;如何映射?
 			无法使用 <id>和<result>,因为这两个标签都是值映射,无法映射集合
 			解决方案:使用标签
 			<collection property="" column="" select=""/>
 			property :需要映射的集合属性,此场景就是 employees 集合
 			column :映射集合数据需要的数据列,此场景就是 部门的 id
 			select : 调用能够返回 employees 集合 对应的查询功能
 				规则:命名空间 +.+功能id,如果在同一个命名空间下面可以省略 命名空间
 		 -->
 		 <collection property="employees" column="id" select="selectEmployeesByDeptId"/>
	</resultMap>
	<!-- 联合查询专用功能,在员工表中,根据 部门的id 查询所有的对应的员工,返回的是一个集合 -->
	<select id="selectEmployeesByDeptId" resultType="cn.xc.mybatis.pojo.Employee">
		select * from employee where dept_id = #{dept_id}
	</select>
</mapper>
运行结果

在这里插入图片描述

等值连接查询

映射代码
<?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">

<mapper namespace="cn.xc.mybatis.mapper.One2ManyMapper">
	<!-- 根据部门的id查询出部门的所有信息 -->
	<select id="selectByPrimaryKey" resultMap="dept_id">
		select e.id e_id,e.name e_name,d.id d_id,d.name d_name
		from employee e inner join department d on e.dept_id = d.id
		where d.id = #{id}
	</select>
	
	<!-- 手动结果集映射 -->
	<resultMap type="cn.xc.mybatis.pojo.Department" id="dept_id">
		<id column="d_id" property="id"/>
		<result column="d_name" property="name"/>
		<!-- 
 			问题:	List<Employee> employees;如何映射?
 			无法使用 <id>和<result>,因为这两个标签都是值映射,无法映射集合
 			解决方案:使用标签
 			<collection property="" column="" select=""/>
 			property :需要映射的集合属性,此场景就是 employees 集合
			ofType : 映射集合的泛型的数据类型 cn.xc.mybatis.pojo.Employee
 		 -->
 		 <collection property="employees" ofType="cn.xc.mybatis.pojo.Employee">
 			<!-- 主键列映射 -->
 		 	<id property="id" column="e_id"/>
 		 	<!-- 非主键类映射 -->
 		 	<result property="name" column="e_name"/>
 		 </collection>
	</resultMap>
	
</mapper>
运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值