实验五 MyBatis的关联映射
- 实验目的
1、了解数据表之间以及对象之间的三种关联关系;
2、理解关联关系中的嵌套查询和嵌套结果的区别;
3、掌握一对一、一对多和多对多关联映射的使用;
- 实验内容
1、已知数据库MyBatisRelation中存在以下几个表:
a. 学生(Student):id(int, primary key, auto increment),Name(姓名,varchar),Birthday(出生日期,date),性别(Sex,varchar)
b. 学生证(StudentIDCard):id(int, primary key, auto increment),StuNo(学号,long)
c. 班级(Class):id(int, primary key, auto increment),Specialty(专业,varchar),Grade(年级,int),Class(班,int)
d. 课程(Course):id(int, primary key, auto increment),Name(课程名,varchar)
现建立以下的关联关系:学生与学生证、学生与班级、学生与课程的选课。分别说出这三种关系属于MyBatis关联关系的哪种类型,通过在相应表中添加合适的外键或创建中间表的方式实现这些关联关系,并创建相应的类,实现以下的查询:
答:学生与课程的选课
a. 学生与学生证: 一对一关联, 每个学生只能拥有一张学生证,每张学生证也只能属于一个学生。学生证表中添加一个sid列作为外键,与学生表的id列关联。
b. 学生与班级: 一对多关联,一个班级可以有多个学生,但是一个学生只能属于一个班级。
学生表中添加一个classid列作为外键,与班级表的id列关联
c. 学生与课程的选课:多对多关联,因为一个学生可以选修多门课程,同时一门课程也可以被多个学生选修。创建一个中间表student_course来实现,中间表包含学生表的id(sid)列和课程表的id( cid)列作为外键,用来表示学生选修的课程。
(1)通过Student表的id查找该学生的信息,并同时获取其学号;
(2)通过Class表的id查找某个班级的信息,并同时查找该班级的所有学生信息;
(3)通过Student表的id查找该学生的信息,并同时获取其选课信息。
以上每种查询都使用嵌套查询和嵌套结果查询实现。
- 实验结果
- 实验代码
package com.example.mapper;
import java.util.List;
public class Class {
private int id;
private String specialty;
private int grade;
private int classNo;
private List<Student> students;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSpecialty() {
return specialty;
}
public void setSpecialty(String specialty) {
this.specialty = specialty;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public int getClassNo() {
return classNo;
}
public void setClassNo(int classNo) {
this.classNo = classNo;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "Class{" +
"id=" + id +
", specialty='" + specialty + '\'' +
", grade=" + grade +
", classNo=" + classNo +
", students=" + students +
'}';
}
}
package com.example.mapper;
public class Course {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Course{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package com.example.mapper;
import java.util.Date;
import java.util.List;
public class Student {
private int id;
private String name;
private Date birthday;
private String sex;
private int classId;
private List<Course> courses; // 新增的属性
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getClassId() {
return classId;
}
public void setClassId(int classId) {
this.classId = classId;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", classId=" + classId +
", courses=" + courses +
'}';
}
}
package com.example.mapper;
public class StudentCourse {
private int id;
private int sid;
private int courseid;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public int getCourseid() {
return courseid;
}
public void setCourseid(int courseid) {
this.courseid = courseid;
}
// getters and setters
}
package com.example.mapper;
import java.util.List;
public interface StudentCourseMapper {
// 通过学生id查询学生信息以及学号
Student findStudentById(int id);
// 通过班级id查询班级信息以及所有学生信息
Class findClassById(int id);
// 通过学生id查询学生信息以及其选课信息
Student findStudentCourseById(int id);
}
package com.example.mapper;
public class StudentIDCard {
private int id;
private long stuNo;
private int sid;
// getter and setter methods
// ...
}
package com.example.mapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
class MyBatisTest {
public static void main(String[] args) {
// 读取mybatis-config.xml配置文件
InputStream inputStream = MyBatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
StudentCourseMapper studentCourseMapper = sqlSession.getMapper(StudentCourseMapper.class);
// 测试通过学生id查询学生信息以及学号
System.out.println("测试通过学生id时=1查询学生信息以及学号");
Student student = studentCourseMapper.findStudentById(1);
System.out.println(student);
// 测试通过班级id查询班级信息以及所有学生信息
System.out.println("测试通过班级id=1时查询班级信息以及所有学生信息");
Class cls = studentCourseMapper.findClassById(1);
System.out.println(cls);
// 测试通过学生id查询学生信息以及其选课信息
System.out.println("测试通过学生id=1查询学生信息以及其选课信息");
Student studentCourse = studentCourseMapper.findStudentCourseById(1);
System.out.println(studentCourse);
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/MyBatisRelation" />
<property name="username" value="root" />
<property name="password" value="2636099699" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="StudentMapper.xml" />
</mappers>
</configuration>
<?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="com.example.mapper.StudentCourseMapper">
<!-- 通过学生id查询学生信息以及学号 -->
<select id="findStudentById" resultMap="studentResultMap">
SELECT s.*, i.StuNo
FROM Student s
LEFT JOIN StudentIDCard i ON s.id = i.sid
WHERE s.id = #{id}
</select>
<!-- 通过班级id查询班级信息以及所有学生信息 -->
<select id="findClassById" resultMap="classResultMap">
SELECT c.*, s.*
FROM Class c
LEFT JOIN Student s ON c.id = s.classid
WHERE c.id = #{id}
</select>
<!-- 通过学生id查询学生信息以及其选课信息 -->
<select id="findStudentCourseById" resultMap="studentResultMap">
SELECT s.*, c.id AS courseid, c.Name AS coursename
FROM Student s
LEFT JOIN Student_Course sc ON s.id = sc.sid
LEFT JOIN Course c ON sc.courseid = c.id
WHERE s.id = #{id}
</select>
<!-- 定义结果映射:学生信息和学号 -->
<resultMap id="studentResultMap" type="com.example.mapper.Student">
<id property="id" column="id"/>
<result property="name" column="Name"/>
<result property="birthday" column="Birthday"/>
<result property="sex" column="Sex"/>
<result property="classId" column="classid"/>
<!-- 定义关联的选课信息 -->
<collection property="courses" ofType="com.example.mapper.Course">
<id property="id" column="courseid"/>
<result property="name" column="coursename"/>
</collection>
</resultMap>
<!-- 定义结果映射:班级信息和学生列表 -->
<resultMap id="classResultMap" type="com.example.mapper.Class">
<id property="id" column="id"/>
<result property="specialty" column="Specialty"/>
<result property="grade" column="Grade"/>
<result property="classNo" column="Class"/>
<!-- 定义关联的学生列表 -->
<collection property="students" ofType="com.example.mapper.Student">
<id property="id" column="id"/>
<result property="name" column="Name"/>
<result property="birthday" column="Birthday"/>
<result property="sex" column="Sex"/>
</collection>
</resultMap>
</mapper>
- 实验心得
这次实验让我更加深入地理解了数据库中的三种关联关系,以及如何在MyBatis中进行关联映射。学生与学生证、学生与班级、学生与课程的选课分别对应了一对一、一对多和多对多关联映射。在实现这些关联关系的过程中,需要通过添加外键或创建中间表来建立关联,这也让我更加熟悉了数据库的设计与操作。在MyBatis中,使用resultMap标签定义了对象之间的关联关系,使用select标签进行嵌套查询,同时还可以使用嵌套结果来优化查询性能。
在这个实验中,我通过编写代码实现了这些关联关系的查询,并进行了测试。通过这个实验,我不仅掌握了MyBatis中关联映射的基本用法,还对数据库的设计和操作有了更深入的了解。同时,我也意识到了数据库中关联关系的重要性,只有通过建立正确的关联关系才能实现数据库的高效操作和数据查询。这次实验让我受益匪浅,我会继续深入学习数据库和MyBatis相关知识,为以后的开发工作做好充分的准备。