spring boot整合mybatis
项目结构
controller
package com.qcby.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping;@Controller public class HomeController {@GetMapping("/")public String index() {return "index";} }
package com.qcby.controller;import com.qcby.domain.Student; import com.qcby.domain.Teacher; import com.qcby.service.StudentService; import com.qcby.service.TeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*;@Controller @RequestMapping("/students") public class StudentController {@Autowiredprivate StudentService studentService;@Autowiredprivate TeacherService teacherService;// 显示所有学生@GetMappingpublic String list(Model model) {model.addAttribute("students", studentService.findAll());return "student/list";}// 显示添加学生表单@GetMapping("/add")public String addForm(Model model) {model.addAttribute("student", new Student());model.addAttribute("teachers", teacherService.findAll());return "student/form";}// 保存学生@PostMapping("/save")public String save(@ModelAttribute Student student) {if (student.getId() == null) {studentService.insert(student);} else {studentService.update(student);}return "redirect:/students";}// 显示编辑学生表单@GetMapping("/edit/{id}")public String editForm(@PathVariable Integer id, Model model) {model.addAttribute("student", studentService.findById(id));model.addAttribute("teachers", teacherService.findAll());return "student/form";}// 删除学生@GetMapping("/delete/{id}")public String delete(@PathVariable Integer id) {studentService.delete(id);return "redirect:/students";}// 按教师ID查询学生@GetMapping("/by-teacher/{teacherId}")public String listByTeacher(@PathVariable Integer teacherId, Model model) {model.addAttribute("students", studentService.findByTeacherId(teacherId));Teacher teacher = teacherService.findById(teacherId);model.addAttribute("teacherName", teacher != null ? teacher.getName() : "未知教师");return "student/list-by-teacher";} }
package com.qcby.controller;import com.qcby.domain.Teacher; import com.qcby.service.TeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*;@Controller @RequestMapping("/teachers") public class TeacherController {@Autowiredprivate TeacherService teacherService;// 显示所有教师@GetMappingpublic String list(Model model) {model.addAttribute("teachers", teacherService.findAll());return "teacher/list";}// 显示添加教师表单@GetMapping("/add")public String addForm(Model model) {model.addAttribute("teacher", new Teacher());return "teacher/form";}// 保存教师@PostMapping("/save")public String save(@ModelAttribute Teacher teacher) {if (teacher.getId() == null) {teacherService.insert(teacher);} else {teacherService.update(teacher);}return "redirect:/teachers";}// 显示编辑教师表单@GetMapping("/edit/{id}")public String editForm(@PathVariable Integer id, Model model) {model.addAttribute("teacher", teacherService.findById(id));return "teacher/form";}// 删除教师@GetMapping("/delete/{id}")public String delete(@PathVariable Integer id) {teacherService.delete(id);return "redirect:/teachers";} }
domain
package com.qcby.domain;import lombok.Data; import java.time.LocalDateTime;@Data public class Student {private Integer id;private String name;private Integer age;private String gender;private String grade;private Integer teacherId;private String teacherName; // 用于显示教师姓名,不映射到数据库private LocalDateTime createTime;private LocalDateTime updateTime; }
package com.qcby.domain;import lombok.Data; import java.time.LocalDateTime;@Data public class Teacher {private Integer id;private String name;private Integer age;private String subject;private String phone;private String email;private LocalDateTime createTime;private LocalDateTime updateTime; }
mapper
package com.qcby.mapper;import com.qcby.domain.Student; import org.apache.ibatis.annotations.Mapper; import java.util.List;@Mapper public interface StudentMapper {// 查询所有学生List<Student> findAll();// 根据ID查询学生Student findById(Integer id);// 添加学生int insert(Student student);// 更新学生int update(Student student);// 删除学生int delete(Integer id);// 根据教师ID查询学生List<Student> findByTeacherId(Integer teacherId); }
package com.qcby.mapper;import com.qcby.domain.Teacher; import org.apache.ibatis.annotations.Mapper; import java.util.List;@Mapper public interface TeacherMapper {// 查询所有教师List<Teacher> findAll();// 根据ID查询教师Teacher findById(Integer id);// 添加教师int insert(Teacher teacher);// 更新教师int update(Teacher teacher);// 删除教师int delete(Integer id); }
service
package com.qcby.service;import com.qcby.domain.Student;import java.util.List;public interface StudentService {List<Student> findAll();Student findById(Integer id);int insert(Student student);int update(Student student);int delete(Integer id);List<Student> findByTeacherId(Integer teacherId); }
package com.qcby.service;import com.qcby.domain.Teacher;import java.util.List;public interface TeacherService {List<Teacher> findAll();Teacher findById(Integer id);int insert(Teacher teacher);int update(Teacher teacher);int delete(Integer id); }
package com.qcby.service.impl;import com.qcby.domain.Student; import com.qcby.mapper.StudentMapper; import com.qcby.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List;@Service public class StudentServiceImpl implements StudentService {@Autowiredprivate StudentMapper studentMapper;@Overridepublic List<Student> findAll() {return studentMapper.findAll();}@Overridepublic Student findById(Integer id) {return studentMapper.findById(id);}@Overridepublic int insert(Student student) {return studentMapper.insert(student);}@Overridepublic int update(Student student) {return studentMapper.update(student);}@Overridepublic int delete(Integer id) {return studentMapper.delete(id);}@Overridepublic List<Student> findByTeacherId(Integer teacherId) {return studentMapper.findByTeacherId(teacherId);} }
package com.qcby.service.impl;import com.qcby.domain.Teacher; import com.qcby.mapper.TeacherMapper; import com.qcby.service.TeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List;@Service public class TeacherServiceImpl implements TeacherService {@Autowiredprivate TeacherMapper teacherMapper;@Overridepublic List<Teacher> findAll() {return teacherMapper.findAll();}@Overridepublic Teacher findById(Integer id) {return teacherMapper.findById(id);}@Overridepublic int insert(Teacher teacher) {return teacherMapper.insert(teacher);}@Overridepublic int update(Teacher teacher) {return teacherMapper.update(teacher);}@Overridepublic int delete(Integer id) {return teacherMapper.delete(id);} }
mapper.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="com.qcby.mapper.StudentMapper"><resultMap id="StudentResultMap" type="com.qcby.domain.Student"><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/><result property="gender" column="gender"/><result property="grade" column="grade"/><result property="teacherId" column="teacher_id"/><result property="teacherName" column="teacher_name"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/></resultMap><select id="findAll" resultMap="StudentResultMap">SELECT s.*, t.name as teacher_nameFROM student sLEFT JOIN teacher t ON s.teacher_id = t.idORDER BY s.id DESC</select><select id="findById" parameterType="int" resultMap="StudentResultMap">SELECT s.*, t.name as teacher_nameFROM student sLEFT JOIN teacher t ON s.teacher_id = t.idWHERE s.id = #{id}</select><select id="findByTeacherId" parameterType="int" resultMap="StudentResultMap">SELECT s.*, t.name as teacher_nameFROM student sLEFT JOIN teacher t ON s.teacher_id = t.idWHERE s.teacher_id = #{teacherId}ORDER BY s.id DESC</select><insert id="insert" parameterType="com.qcby.domain.Student">INSERT INTO student (name, age, gender, grade, teacher_id)VALUES (#{name}, #{age}, #{gender}, #{grade}, #{teacherId})</insert><update id="update" parameterType="com.qcby.domain.Student">UPDATE studentSET name = #{name},age = #{age},gender = #{gender},grade = #{grade},teacher_id = #{teacherId}WHERE id = #{id}</update><delete id="delete" parameterType="int">DELETE FROM student WHERE id = #{id}</delete> </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="com.qcby.mapper.TeacherMapper"><resultMap id="TeacherResultMap" type="com.qcby.domain.Teacher"><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/><result property="subject" column="subject"/><result property="phone" column="phone"/><result property="email" column="email"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/></resultMap><select id="findAll" resultMap="TeacherResultMap">SELECT * FROM teacher ORDER BY id DESC</select><select id="findById" parameterType="int" resultMap="TeacherResultMap">SELECT * FROM teacher WHERE id = #{id}</select><insert id="insert" parameterType="com.qcby.domain.Teacher">INSERT INTO teacher (name, age, subject, phone, email)VALUES (#{name}, #{age}, #{subject}, #{phone}, #{email})</insert><update id="update" parameterType="com.qcby.domain.Teacher">UPDATE teacherSET name = #{name},age = #{age},subject = #{subject},phone = #{phone},email = #{email}WHERE id = #{id}</update><delete id="delete" parameterType="int">DELETE FROM teacher WHERE id = #{id}</delete> </mapper>
html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title th:text="${student.id != null ? '编辑学生' : '添加学生'}"></title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-4"><h2 th:text="${student.id != null ? '编辑学生' : '添加学生'}"></h2><form th:action="@{/students/save}" th:object="${student}" method="post" class="mt-4"><input type="hidden" th:field="*{id}" /><div class="mb-3"><label for="name" class="form-label">姓名</label><input type="text" class="form-control" id="name" th:field="*{name}" required /></div><div class="mb-3"><label for="age" class="form-label">年龄</label><input type="number" class="form-control" id="age" th:field="*{age}" min="6" max="20" /></div><div class="mb-3"><label for="gender" class="form-label">性别</label><select class="form-select" id="gender" th:field="*{gender}"><option value="">请选择</option><option value="男">男</option><option value="女">女</option></select></div><div class="mb-3"><label for="grade" class="form-label">年级</label><input type="text" class="form-control" id="grade" th:field="*{grade}" /></div><div class="mb-3"><label for="teacherId" class="form-label">班主任</label><select class="form-select" id="teacherId" th:field="*{teacherId}"><option value="">请选择</option><option th:each="teacher : ${teachers}"th:value="${teacher.id}"th:text="${teacher.name}"></option></select></div><div class="mb-3"><button type="submit" class="btn btn-primary">保存</button><a href="/students" class="btn btn-secondary ms-2">取消</a></div></form> </div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>学生列表</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-4"><div class="d-flex justify-content-between align-items-center mb-4"><h2>学生列表</h2><a href="/students/add" class="btn btn-primary">添加学生</a></div><a href="/" class="btn btn-secondary mb-3">返回首页</a><table class="table table-striped table-hover"><thead class="table-dark"><tr><th>ID</th><th>姓名</th><th>年龄</th><th>性别</th><th>年级</th><th>班主任</th><th>操作</th></tr></thead><tbody><tr th:each="student : ${students}"><td th:text="${student.id}"></td><td th:text="${student.name}"></td><td th:text="${student.age}"></td><td th:text="${student.gender}"></td><td th:text="${student.grade}"></td><td th:text="${student.teacherName}"></td><td><a th:href="@{/students/edit/{id}(id=${student.id})}" class="btn btn-sm btn-warning">编辑</a><a th:href="@{/students/delete/{id}(id=${student.id})}" class="btn btn-sm btn-danger"onclick="return confirm('确定要删除吗?')">删除</a></td></tr></tbody></table> </div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>学生列表</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-4"><div class="d-flex justify-content-between align-items-center mb-4"><h2><span th:text="${teacherName}"></span> 的学生列表</h2><a href="/students/add" class="btn btn-primary">添加学生</a></div><div class="mb-3"><a href="/" class="btn btn-secondary">返回首页</a><a href="/teachers" class="btn btn-info ms-2">返回教师列表</a><a href="/students" class="btn btn-success ms-2">查看所有学生</a></div><table class="table table-striped table-hover"><thead class="table-dark"><tr><th>ID</th><th>姓名</th><th>年龄</th><th>性别</th><th>年级</th><th>操作</th></tr></thead><tbody><tr th:each="student : ${students}"><td th:text="${student.id}"></td><td th:text="${student.name}"></td><td th:text="${student.age}"></td><td th:text="${student.gender}"></td><td th:text="${student.grade}"></td><td><a th:href="@{/students/edit/{id}(id=${student.id})}" class="btn btn-sm btn-warning">编辑</a><a th:href="@{/students/delete/{id}(id=${student.id})}" class="btn btn-sm btn-danger"onclick="return confirm('确定要删除吗?')">删除</a></td></tr></tbody></table> </div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title th:text="${teacher.id != null ? '编辑教师' : '添加教师'}"></title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-4"><h2 th:text="${teacher.id != null ? '编辑教师' : '添加教师'}"></h2><form th:action="@{/teachers/save}" th:object="${teacher}" method="post" class="mt-4"><input type="hidden" th:field="*{id}" /><div class="mb-3"><label for="name" class="form-label">姓名</label><input type="text" class="form-control" id="name" th:field="*{name}" required /></div><div class="mb-3"><label for="age" class="form-label">年龄</label><input type="number" class="form-control" id="age" th:field="*{age}" min="18" max="65" /></div><div class="mb-3"><label for="subject" class="form-label">科目</label><input type="text" class="form-control" id="subject" th:field="*{subject}" /></div><div class="mb-3"><label for="phone" class="form-label">电话</label><input type="text" class="form-control" id="phone" th:field="*{phone}" /></div><div class="mb-3"><label for="email" class="form-label">邮箱</label><input type="email" class="form-control" id="email" th:field="*{email}" /></div><div class="mb-3"><button type="submit" class="btn btn-primary">保存</button><a href="/teachers" class="btn btn-secondary ms-2">取消</a></div></form> </div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>教师列表</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-4"><div class="d-flex justify-content-between align-items-center mb-4"><h2>教师列表</h2><a href="/teachers/add" class="btn btn-primary">添加教师</a></div><a href="/" class="btn btn-secondary mb-3">返回首页</a><table class="table table-striped table-hover"><thead class="table-dark"><tr><th>ID</th><th>姓名</th><th>年龄</th><th>科目</th><th>电话</th><th>邮箱</th><th>学生</th><th>操作</th></tr></thead><tbody><tr th:each="teacher : ${teachers}"><td th:text="${teacher.id}"></td><td th:text="${teacher.name}"></td><td th:text="${teacher.age}"></td><td th:text="${teacher.subject}"></td><td th:text="${teacher.phone}"></td><td th:text="${teacher.email}"></td><td><a th:href="@{/students/by-teacher/{id}(id=${teacher.id})}" class="btn btn-sm btn-info">查看学生</a></td><td><a th:href="@{/teachers/edit/{id}(id=${teacher.id})}" class="btn btn-sm btn-warning">编辑</a><a th:href="@{/teachers/delete/{id}(id=${teacher.id})}" class="btn btn-sm btn-danger"onclick="return confirm('确定要删除吗?')">删除</a></td></tr></tbody></table> </div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>教师学生管理系统</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-5"><div class="jumbotron text-center"><h1 class="display-4">教师学生管理系统</h1><p class="lead">简单高效的教学管理解决方案</p><hr class="my-4"><div class="d-flex justify-content-center gap-3"><a class="btn btn-primary btn-lg" href="/teachers" role="button">教师管理</a><a class="btn btn-success btn-lg" href="/students" role="button">学生管理</a></div></div> </div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
properties
# ????? server.port=8080# ????? spring.datasource.url=jdbc:mysql://localhost:3306/teacher_student_management?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# MyBatis?? mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.qcby.domain# Thymeleaf?? spring.thymeleaf.cache=false spring.thymeleaf.mode=HTML5 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.servlet.content-type=text/html# ???? logging.level.com.example.mapper=debug