Spring+SpringMVC+MyBatis深入学习及搭建(六)——MyBatis关联查询
在实际的项目开发中,数据库表之间往往存在着各种关联关系,如一对一、一对多、多对多等。MyBatis 作为一款优秀的持久层框架,提供了强大的关联查询功能,能够方便地处理这些表间关联。本文将深入探讨 MyBatis 的关联查询,包括一对一、一对多和多对多关联查询的实现方式,并结合示例代码进行详细讲解。
目录#
- 一对一关联查询
- 需求场景
- 实现方式
- 示例代码
- 一对多关联查询
- 需求场景
- 实现方式
- 示例代码
- 多对多关联查询
- 需求场景
- 实现方式
- 示例代码
- 总结
- 参考资料
1. 一对一关联查询#
需求场景#
在数据库中,一个用户可能对应一个详细的用户信息,如用户的联系方式、地址等。在查询用户信息时,往往需要同时查询其对应的详细信息,这就是一对一关联查询的典型场景。
实现方式#
MyBatis 实现一对一关联查询主要有两种方式:嵌套查询和嵌套结果。
- 嵌套查询:通过执行多个 SQL 语句,先查询主表数据,再根据主表数据的关联字段查询关联表数据。
- 嵌套结果:通过一个 SQL 语句查询主表和关联表的数据,然后在映射文件中进行结果映射。
示例代码#
假设我们有两个表:user 表和 user_info 表,它们通过 user_id 进行关联。
实体类#
// User.java
public class User {
private Integer id;
private String username;
private UserInfo userInfo;
// 省略 getter 和 setter 方法
}
// UserInfo.java
public class UserInfo {
private Integer id;
private String phone;
private String address;
// 省略 getter 和 setter 方法
}映射文件(嵌套查询方式)#
<mapper namespace="com.example.mapper.UserMapper">
<select id="getUserById" resultMap="UserResultMap">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="getUserInfoByUserId" resultType="com.example.entity.UserInfo">
SELECT * FROM user_info WHERE user_id = #{userId}
</select>
<resultMap id="UserResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<association property="userInfo" column="id" select="getUserInfoByUserId"/>
</resultMap>
</mapper>映射文件(嵌套结果方式)#
<mapper namespace="com.example.mapper.UserMapper">
<select id="getUserById" resultMap="UserResultMap">
SELECT u.id, u.username, ui.id as info_id, ui.phone, ui.address
FROM user u
LEFT JOIN user_info ui ON u.id = ui.user_id
WHERE u.id = #{id}
</select>
<resultMap id="UserResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<association property="userInfo" javaType="com.example.entity.UserInfo">
<id property="id" column="info_id"/>
<result property="phone" column="phone"/>
<result property="address" column="address"/>
</association>
</resultMap>
</mapper>2. 一对多关联查询#
需求场景#
在数据库中,一个部门可能有多个员工,在查询部门信息时,需要同时查询该部门下的所有员工信息,这就是一对多关联查询的典型场景。
实现方式#
MyBatis 实现一对多关联查询同样可以使用嵌套查询和嵌套结果两种方式。
示例代码#
假设我们有两个表:department 表和 employee 表,它们通过 department_id 进行关联。
实体类#
// Department.java
public class Department {
private Integer id;
private String departmentName;
private List<Employee> employees;
// 省略 getter 和 setter 方法
}
// Employee.java
public class Employee {
private Integer id;
private String employeeName;
// 省略 getter 和 setter 方法
}映射文件(嵌套查询方式)#
<mapper namespace="com.example.mapper.DepartmentMapper">
<select id="getDepartmentById" resultMap="DepartmentResultMap">
SELECT * FROM department WHERE id = #{id}
</select>
<select id="getEmployeesByDepartmentId" resultType="com.example.entity.Employee">
SELECT * FROM employee WHERE department_id = #{departmentId}
</select>
<resultMap id="DepartmentResultMap" type="com.example.entity.Department">
<id property="id" column="id"/>
<result property="departmentName" column="department_name"/>
<collection property="employees" column="id" select="getEmployeesByDepartmentId"/>
</resultMap>
</mapper>映射文件(嵌套结果方式)#
<mapper namespace="com.example.mapper.DepartmentMapper">
<select id="getDepartmentById" resultMap="DepartmentResultMap">
SELECT d.id, d.department_name, e.id as employee_id, e.employee_name
FROM department d
LEFT JOIN employee e ON d.id = e.department_id
WHERE d.id = #{id}
</select>
<resultMap id="DepartmentResultMap" type="com.example.entity.Department">
<id property="id" column="id"/>
<result property="departmentName" column="department_name"/>
<collection property="employees" ofType="com.example.entity.Employee">
<id property="id" column="employee_id"/>
<result property="employeeName" column="employee_name"/>
</collection>
</resultMap>
</mapper>3. 多对多关联查询#
需求场景#
在数据库中,一个学生可以选择多门课程,一门课程也可以被多个学生选择,这就是多对多关联查询的典型场景。通常需要通过一个中间表来建立学生和课程之间的关联。
实现方式#
多对多关联查询可以通过嵌套查询和嵌套结果两种方式实现,核心是处理好中间表的关联。
示例代码#
假设我们有三个表:student 表、course 表和 student_course 中间表。
实体类#
// Student.java
public class Student {
private Integer id;
private String studentName;
private List<Course> courses;
// 省略 getter 和 setter 方法
}
// Course.java
public class Course {
private Integer id;
private String courseName;
// 省略 getter 和 setter 方法
}映射文件(嵌套查询方式)#
<mapper namespace="com.example.mapper.StudentMapper">
<select id="getStudentById" resultMap="StudentResultMap">
SELECT * FROM student WHERE id = #{id}
</select>
<select id="getCoursesByStudentId" resultType="com.example.entity.Course">
SELECT c.*
FROM course c
JOIN student_course sc ON c.id = sc.course_id
WHERE sc.student_id = #{studentId}
</select>
<resultMap id="StudentResultMap" type="com.example.entity.Student">
<id property="id" column="id"/>
<result property="studentName" column="student_name"/>
<collection property="courses" column="id" select="getCoursesByStudentId"/>
</resultMap>
</mapper>映射文件(嵌套结果方式)#
<mapper namespace="com.example.mapper.StudentMapper">
<select id="getStudentById" resultMap="StudentResultMap">
SELECT s.id, s.student_name, c.id as course_id, c.course_name
FROM student s
LEFT JOIN student_course sc ON s.id = sc.student_id
LEFT JOIN course c ON sc.course_id = c.id
WHERE s.id = #{id}
</select>
<resultMap id="StudentResultMap" type="com.example.entity.Student">
<id property="id" column="id"/>
<result property="studentName" column="student_name"/>
<collection property="courses" ofType="com.example.entity.Course">
<id property="id" column="course_id"/>
<result property="courseName" column="course_name"/>
</collection>
</resultMap>
</mapper>总结#
MyBatis 的关联查询功能为处理数据库表间关联提供了强大的支持。通过嵌套查询和嵌套结果两种方式,我们可以方便地实现一对一、一对多和多对多关联查询。在实际开发中,需要根据具体的业务需求和性能要求选择合适的实现方式。
参考资料#
- 《MyBatis 官方文档》
- 《Spring+MyBatis 企业应用实战》
以上就是关于 MyBatis 关联查询的详细介绍,希望对你有所帮助。