目录
Gitee下载地址:springboot+mybatis实现多对一demo(JavaEE第二次作业)
某学生和课程的ER图如下图所示,根据ER图创建数据库表,往数据库表中添加若干测试数据,用SpringBoot+SpringMVC+ Mybatis完成如下功能:
1、用前端列表显示所有的学生的选课信息,学生的选课信息通过级联查询获取
2、删除某条学生信息,并同步的删除该学生的选课信息
3、前端完成输入用户的姓名后查询该用户所选的课程

真服了,写完了才发现自己的命名不符合要求。所以我会教你们如何把这个作业变成你们“自己”的作业!!!!当然如果单纯知识来学习知识的就不用关注这么多啦~~
系列文章:
springmvc实现增删改查博文参考:springmvc实现增删改查(创建一个bookstore数据库)
新建一个springboot项目参考博文:springboot新建一个项目以及各种报错解决
springboot整合mybatis实现简单增删改查参考博文:springboot整合mybatis实现简单增删改查
springboot实现多表一对一查询参考博文:springboot+mybatis实现多表一对一查询

手动补一个依赖:
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-thymeleafartifactId>
- dependency>



新建两个Java类:
Course:
- package com.hnucm.c202001090145.pojo;
-
- import lombok.Data;
-
- @Data
- public class Course {
- private int id;
- private String c_name;
- private float score;
- }
Student类:
- package com.hnucm.c202001090145.pojo;
-
- import lombok.Data;
-
- import java.util.List;
-
- @Data
- public class Student {
- private String num;
- private String name;
- private String classname;
- private List
courseList; -
- }
我在这里数据库配置后面新增了一个属性:allowMultiQueries=true
你们直接复制粘贴就OK。这条配置项的作用是允许执行多条sql语句,我这里是使用在delete标签删除时里面含有两条独立的SQL语句。不配置会报错
-
-
- #设置端口号
- server.port=9090
- #前缀值,路劲前面加上/springboot
- server.servlet.context-path=/springboot
- #设置静态文件访问地址
- spring.web.resources.static-locations=classpath:/templates
- #把你自己的数据库名写在‘3306/’ 后面
- #spring.datasource.url=jdbc:mysql://localhost:3306/homework_tow?
- characterEncoding=utf8&serverTimezone=UTC
- spring.datasource.url=jdbc:mysql://localhost:3306/homework_tow?characterEncoding=utf8&serverTimezone=UTC&allowMultiQueries=true
- # 用户名密码
- spring.datasource.username=root
- spring.datasource.password=1234
- spring.datasource.name=defaultDataSource
-
-
- #改成你自己的路径。!!!!!!改
- mybatis.type-aliases-package=com.hnucm.c202001090145.pojo
-
- mybatis.mapper-locations=classpath:mappers/*.xml
- # 日志
- logging.level.com.example.csdn_release=debug
简单的我就快速过了,仔细讲讲核心代码
在这里主要是定义了几个方法,以及与StudentMapper.xml文件关联
- package com.hnucm.c202001090145.mapper;
-
- import com.hnucm.c202001090145.pojo.CourseOYH;
- import org.apache.ibatis.annotations.Mapper;
-
- import java.util.List;
-
- @Mapper
- public interface StudentMapper {
- // 查询所有学生以及选课情况
-
- public List
findAllStuAndCourse(); - int deleteStudentByNum(String num);
-
- }
- package com.hnucm.c202001090145.mapper;
-
- import com.hnucm.c202001090145.pojo.CourseOYH;
- import org.apache.ibatis.annotations.Mapper;
-
- import java.util.List;
-
- @Mapper
- public interface CourseMapper {
- public List
findCourseById(String num); - // 输入用户姓名查询所选课程
- List
findCourseByName(String name); - }
着重讲xml文件。首先是一个select标签。因为要展示学生的所有信息,所以直接select*。与之对应的是resultMap标签,因为学生和选课是一对多的关系,所以需要一个集合关系。这也是为什么在pojo中的student加了一个List的原因。其实主要还是collection标签中的类容,里面的property=“courseList” 中的courseList是属性名,什么叫属性名呢?以及一些springboot中一些常用的名词解释可以看我这篇文章:springboot+mybatis实现多表一对一查询以及名词解释
里面的column是
select="com.hnucm.c202001090145.mapper.CourseMapper.findCourseById" 这个对应方法所需要的参数ofType意思是这个集合的类型。
下面的delete标签是删除学生信息和选课信息。可以看见这里面包含了两条独立的sql语句。springboot默认是不允许的所以我们在上面的配置文件中加了spring.datasource.url=jdbc:mysql://localhost:3306/homework_tow?characterEncoding=utf8&serverTimezone=UTC&allowMultiQueries=true
标红的部分就可以实现同时执行多条SQL语句了
- "1.0" encoding="UTF-8"?>
- mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.hnucm.c202001090145.mapper.StudentMapper">
- <select id="findAllStuAndCourse" resultMap="studentCourse">
- select * from student_oyh
- select>
-
- <resultMap id="studentCourse" type="com.hnucm.c202001090145.pojo.StudentOYH">
- <id column="num" property="num">id>
- <result property="name" column="name">result>
- <result column="classname" property="classname">result>
- <collection property="courseList"
- ofType="com.hnucm.c202001090145.pojo.CourseOYH"
- column="num"
- select="com.hnucm.c202001090145.mapper.CourseMapper.findCourseById">
- collection>
- resultMap>
- <delete id="deleteStudentByNum" parameterType="String" >
- delete from student_oyh where student_oyh.num=#{num};
- delete from stu_course where stu_course.num=#{num}
- delete>
-
-
-
- mapper>
这里面的第一个select语句就是实现了学生信息以及选课信息的级联查询。只不过我们把它们放在了一条sql语句中了。解释一下,就是先执行
select courseId from stu_course where num=#{num}这条代码,有人说这里的num参数 是怎么来的呢,其实就是StudentMapper.xml文件中collection中的colum传递过来的,并且是一条一条穿过来,所以这条sql语句就会查询出多个 courseId。之后继续执行select * from course_oyh where id in(一个courseId数组)这条语句。第二个select语句,就是输入学生信息查询选课信息。标准的查法应该是
输入姓名查询student表中的num 通过num查询在stu_course表中的所有courseId 将id拿到继续在course中查询但是我不一样呀,我偷懒一句搞定算了~~~~
- "1.0" encoding="UTF-8"?>
- mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.hnucm.c202001090145.mapper.CourseMapper">
- <select id="findCourseById"
- resultType="com.hnucm.c202001090145.pojo.CourseOYH"
- parameterType="String">
- select * from course_oyh where id in(
- select courseId from stu_course where num=#{num}
- )
-
- select>
-
-
- <select id="findCourseByName" parameterType="String" resultType="com.hnucm.c202001090145.pojo.CourseOYH">
- SELECT DISTINCT course_oyh.id,course_oyh.c_name,course_oyh.score
- from stu_course,course_oyh,student_oyh
- where student_oyh.num=stu_course.num AND course_oyh.id=stu_course.courseId and student_oyh.`name`=#{name};
- select>
- mapper>
StudentService接口:
一般接口没有什么好看的就是定义了一些方法
- package com.hnucm.c202001090145.service;
-
-
- import com.hnucm.c202001090145.pojo.CourseOYH;
-
- import java.util.List;
-
- public interface StudentService {
- public List
findAllStuAndCourse(); - int deleteStudentByNum(String num);
- List
findCourseByName(String name); - }
这里也没什么好讲的,就是调用了Mapper层的接口。注意一下“deleteStudentByNum”这个方法上面我多加了一个注解@Transactional,目的是为了防止你只删除了学生信息而没有删除选课信息,从而实现事务回滚
- package com.hnucm.c202001090145.service;
-
- import com.hnucm.c202001090145.mapper.CourseMapper;
- import com.hnucm.c202001090145.mapper.StudentMapper;
- import com.hnucm.c202001090145.pojo.CourseOYH;
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
- import java.util.List;
-
- @Service
- public class StudentServiceImpl implements StudentService{
- @Autowired
- StudentMapper studentMapper;
- @Autowired
- CourseMapper courseMapper;
- @Override
- public List
findAllStuAndCourse() { -
- return studentMapper.findAllStuAndCourse() ;
- }
-
- @Override
- @Transactional
- public int deleteStudentByNum(String num) {
-
- return studentMapper.deleteStudentByNum(num);
- }
-
- @Override
- public List
findCourseByName(String name) { -
- return courseMapper.findCourseByName(name);
- }
- }
这里浅浅讲一下,就是拦截了三个请求,第一个请求“studentlist”是展示所有的学生和选课信息。第二个请求时删除某个学生和它的选课信息。第三个是查询请求
- package com.hnucm.c202001090145.controller;
-
- import com.hnucm.c202001090145.service.StudentService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
-
-
- @Controller
- public class StudentController {
- @Autowired
- StudentService studentService;
- @RequestMapping("studentlist")
- public String StudentList(Model model){
- model.addAttribute("studentlist",studentService.findAllStuAndCourse());
- return "studentlist.html";
- }
- @RequestMapping("deletestudentbyid")
- public String deleteCourse(String num){
- studentService.deleteStudentByNum(num);
- return "redirect:/studentlist";
- }
-
- @RequestMapping("lookinfo")
- public String courseList(Model model, String name){
- model.addAttribute("courseList",studentService.findCourseByName(name));
- model.addAttribute("name",name);
- return "courseList.html";
- }
- }
断点测试是否有数据。如果有数据就继续写html文件

- html>
- <html lang="en" xmlns:th="http://www.thymeleaf.org">
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>用户列表title>
- head>
- <body>
- <table border="1px" cellspacing="0px">
- <tr>
- <th th:width="40px">学号th>
- <th th:width="40px">姓名th>
- <th th:width="150px">班级th>
- <th th:width="150px">选课信息th>
- <th >删除th>
- <th>更新th>
- tr>
-
- <tr th:each="student:${studentlist}">
- <td th:text="${student.num}">td>
-
- <td th:text="${student.name}">td>
-
- <td th:text="${student.classname}">td>
- <td>
- <ul th:each="course:${student.courseList}" >
- <li th:text="${course.c_name}">li>
- <li th:text="${course.score}">li>
- ul>
- td>
-
- <td><a th:href="@{'/deletestudentbyid?num='+${student.num}}">删除用户a> td>
- <td><a th:href="@{updatepersonbyid(num=${student.num},courseId=${student.courseList},classname=${student.classname})}">更新用户a> td>
- tr>
- table>
- <form th:action="@{/lookinfo} " method="post" style="margin-top: 20px">
- 请输入用户名:<input name="name"><br>
- <div><input type="submit" value="查询">div>
- form>
- body>
- html>
用户查询展示页面
- html>
- <html lang="en" xmlns:th="http://www.thymeleaf.org">
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>用户列表title>
- head>
- <body>
- <h2>你所查询的用户:h2>
- <h2 th:text="${name}">h2>
- <h2>选课信息如下:h2>
- <table border="1px" cellspacing="0px">
- <tr>
- <th th:width="40px">课程号th>
- <th th:width="40px">课程名th>
- <th th:width="150px">学分th>
-
- tr>
-
- <tr th:each="course:${courseList}">
- <td th:text="${course.id}">td>
- <td th:text="${course.c_name}">td>
- <td th:text="${course.score}">td>
- tr>
- table>
- body>
- html>
学习知识的不用管这里,完成作业有需要的看看就好了。
第一步修改数据库命名:直接在Navicat中右键表重命名就好了,之后继续在代码中改
与数据库先关的只在xml文件中。只需在每一个xml文件Ctrl+F键搜索没改之前的数据库名,涉及到相关的一个一个手动改!!!注意一定是手动一个一个检查改,不要使用替换!!。
第二步:修改pojo对象类命名:
只需要右键那个类选择refactor,在选择里面的rename就OK了,这里其他的应该不用自己改。
继续重命名Java下面的那个包名,只需要重命名然后在每个文件的最上方改成你的名字就好了。
最容易忽视的地方就是数据库配置文件application.properties中的数据库名,用户名和密码。
还有mybatis对应的pojo类。
然后因为我在配置类中设置了前缀地址/springboot和端口号所以,你运行项目后记得是localhost:9090/springboot/xxx什么的

