学生管理系统(Spring Boot 3.2.0 + MyBatis-Plus 3.5.7)知识点梳理
本文基于 Spring Boot 3.2.0 + MyBatis-Plus 3.5.7 实现学生管理系统(增删改查核心功能,重点梳理分页+多条件查询),同步梳理各层代码知识点、依赖说明、核心API用法,贴合实际开发规范。
一、项目基础配置(核心依赖 + 配置文件)
1.1 核心依赖(pom.xml)
知识点1:Spring Boot 3.x 版本适配:parent 指定 spring-boot-starter-parent 3.2.0,对应 Spring Framework 6.1.x,需使用 MyBatis-Plus 专门为 Spring Boot 3 提供的 starter(mybatis-plus-spring-boot3-starter),否则会出现版本兼容报错(如 factoryBeanObjectType 异常)。
知识点2:核心依赖作用:
-
spring-boot-starter-web:Spring Boot web 核心依赖,提供 HTTP 接口、请求处理等基础能力,无需额外配置 Tomcat(内置)。
-
mybatis-plus-spring-boot3-starter:Spring Boot 3 专用 MyBatis-Plus 启动器,整合 MyBatis-Plus 核心功能,自动配置数据源、SqlSessionFactory 等,简化配置。
-
mysql-connector-j:MySQL 驱动(Spring Boot 3.x 推荐使用此依赖,替代旧版 mysql-connector-java),用于连接 MySQL 数据库。
-
lombok:简化 Java 代码,通过注解(@Data、@RequiredArgsConstructor)自动生成 get/set、构造器、toString 等方法,减少冗余代码。
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<dependencies>
<!-- Spring Boot Web 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot3 专用 MyBatis-Plus 启动器(版本 3.5.7 与 Spring Boot 3.2.0 完全兼容) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<!-- MySQL 驱动(Spring Boot 3.x 推荐使用 mysql-connector-j) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope> <!-- runtime 表示运行时生效,编译时无需依赖 -->
</dependency>
<!-- Lombok 简化代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
1.2 配置文件(application.yml)
知识点1:数据源配置:配置 MySQL 连接信息,url 中需指定时区(serverTimezone=Asia/Shanghai),避免时区异常;driver-class-name 使用 com.mysql.cj.jdbc.Driver(MySQL 8.0+ 推荐)。
知识点2:MyBatis-Plus 配置:log-impl 配置为 stdout,用于在控制台打印 SQL 语句,方便开发调试(生产环境可关闭)。
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root # 替换为你的 MySQL 用户名
password: 123456 # 替换为你的 MySQL 密码
driver-class-name: com.mysql.cj.jdbc.Driver # MySQL 8.0+ 驱动类
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL 日志
二、项目分层设计(SSM/Spring Boot 标准分层)
核心知识点:分层设计原则:职责单一、解耦,便于维护和扩展,各层各司其职:
-
DTO 层:接收前端传递的请求参数,不包含业务逻辑,仅做参数封装。
-
Entity 层:对应数据库表,字段与表字段完全一致,用于数据库操作(MyBatis-Plus 核心操作对象)。
-
Mapper 层:数据访问层,负责与数据库交互,通过 MyBatis-Plus 提供的 BaseMapper 简化 CRUD 操作。
-
Service 层:业务逻辑层,封装核心业务逻辑,调用 Mapper 层完成数据操作,不直接与数据库交互。
-
Controller 层:表现层,接收前端请求,调用 Service 层处理业务,返回结果给前端。
-
Config 层:配置层,用于配置 MyBatis-Plus 分页插件、自定义Bean等。
项目结构:
plain
com.example
├── controller // 控制层:接收请求、返回结果
├── service
│ └── impl // 业务层实现:封装业务逻辑
├── dto // 数据传输层:接收前端请求参数
├── entity // 实体层:对应数据库表
├── mapper // 数据访问层:与数据库交互
├── config // 配置层:分页插件等配置
└── Application // 启动类:项目入口
三、各层代码知识点梳理
3.1 DTO 层(数据传输对象)
知识点1:DTO 作用:专门用于接收前端传递的查询参数,避免直接使用 Entity 接收参数(Entity 对应数据库表,可能包含前端不需要的字段,且不安全)。
知识点2:Lombok @Data 注解:自动生成所有字段的 get/set 方法、toString 方法、equals 和 hashCode 方法,简化代码编写。
知识点3:默认值设置:pageNum 和 pageSize 设置默认值(1 和 10),避免前端未传递分页参数时报错,提升接口健壮性。
java
package com.example.dto;
import lombok.Data;
@Data // Lombok 注解,自动生成 get/set、toString 等方法
public class StudentQueryDTO {
// 多条件查询参数
private String name; // 姓名(模糊查询)
private String className; // 班级(精确查询)
private Integer minScore; // 最低分数(区间查询)
private Integer maxScore; // 最高分数(区间查询)
// 分页参数(设置默认值,前端未传参时使用默认值)
private Integer pageNum = 1; // 默认页码:第1页
private Integer pageSize = 10; // 默认每页条数:10条
}
3.2 Entity 层(实体层)
知识点1:Entity 与数据库表的映射:
-
@TableName("student"):指定当前实体类对应数据库中的 student 表,若实体类名与表名一致,可省略此注解。
-
@TableId(type = IdType.AUTO):指定主键字段,type = IdType.AUTO 表示主键自增(与数据库表中 ID 列的自增设置对应)。
知识点2:字段映射:实体类字段名与数据库表字段名完全一致(大小写不敏感,MySQL 不区分大小写),无需额外配置映射关系;若字段名不一致,可使用 @TableField 注解指定映射关系。
java
package com.example.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data // Lombok 注解,简化代码
@TableName("student") // 映射数据库 student 表
public class Student {
@TableId(type = IdType.AUTO) // 主键自增,对应表中 ID 列
private Integer id; // 对应表中 id 字段(主键)
private String name; // 对应表中 name 字段(姓名)
private Integer age; // 对应表中 age 字段(年龄)
private String idNo; // 对应表中 id_no 字段(身份证号)
private String className; // 对应表中 class 字段(班级,此处字段名与表名一致,无需额外映射)
private Integer score; // 对应表中 score 字段(成绩)
}
3.3 Mapper 层(数据访问层)
知识点1:@Mapper 注解:标记当前接口为 MyBatis 的 Mapper 接口,Spring Boot 会自动扫描该接口,生成代理对象,无需手动创建实现类。
知识点2:继承 BaseMapper<Student>:MyBatis-Plus 提供的 BaseMapper 接口,已封装好所有基础 CRUD 方法(selectById、selectPage、insert、updateById、deleteById 等),无需手动编写 SQL 语句,直接调用即可。
知识点3:自定义 SQL(可选):若基础方法无法满足需求,可在 Mapper 接口中使用 @Select、@Insert 等注解编写自定义 SQL(如示例中注释的 queryStudent 方法)。
java
package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.Student;
import org.apache.ibatis.annotations.Mapper;
// import org.apache.ibatis.annotations.Select;
@Mapper // 标记为 MyBatis Mapper 接口,Spring 自动扫描
public interface StudentMapper extends BaseMapper<Student> {
// 自定义 SQL 示例(可选,基础 CRUD 无需编写)
// @Select("select * from student") // 自定义查询所有学生的 SQL
// ArrayList<Student> queryStudent();
}
3.4 Service 层(业务逻辑层)
3.4.1 Service 接口(StudentService.java)
知识点1:接口定义原则:Service 接口仅定义业务方法,不包含具体实现,便于后续扩展(如多实现类)和维护。
知识点2:Page 分页对象:MyBatis-Plus 提供的 Page 类,用于封装分页信息(页码、每页条数、总条数、分页数据等),作为方法返回值,直接返回给 Controller,无需手动封装分页结果。
java
package com.example.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dto.StudentQueryDTO;
import com.example.entity.Student;
// 业务层接口,定义分页+多条件查询方法
public interface StudentService {
// 接收 DTO 参数,返回分页结果(Page<Student> 包含分页信息和学生列表)
Page<Student> queryStudentByPage(StudentQueryDTO dto);
}
3.4.2 Service 实现类(StudentServiceImpl.java)
知识点1:@Service 注解:标记当前类为 Spring 管理的 Service 组件,Spring 会自动创建该类的实例,供 Controller 调用。
知识点2:依赖注入:
-
@RequiredArgsConstructor(Lombok 注解):自动生成包含所有 final 字段的构造器,Spring 会通过构造器注入 StudentMapper,替代 @Autowired 注解,避免字段注入的弊端(如循环依赖、可测试性差)。
-
StudentMapper 注入:Service 层通过 Mapper 层与数据库交互,不直接操作数据库,符合分层设计原则。
知识点3:分页对象构建:new Page<>(dto.getPageNum(), dto.getPageSize()),传入页码和每页条数,构建分页对象,MyBatis-Plus 会自动处理分页逻辑(拼接 limit 语句)。
知识点4:LambdaQueryWrapper 条件构造器:MyBatis-Plus 提供的 Lambda 条件构造器,用于构建多条件查询语句,优点是:类型安全(避免字段名写错)、语法简洁。
知识点5:条件构造器常用方法:
-
like(condition, column, value):模糊查询,condition 为 true 时才拼接该条件(如 StringUtils.hasText(dto.getName()) 表示姓名不为空时,才进行模糊查询)。
-
eq(condition, column, value):精确查询,condition 为 true 时拼接。
-
ge(condition, column, value):大于等于查询(>=)。
-
le(condition, column, value):小于等于查询(<=)。
知识点6:StringUtils.hasText() 工具类:Spring 提供的工具类,用于判断字符串是否不为 null、不为空字符串、不为空白字符(比 StringUtils.isNotBlank() 更严谨)。
知识点7:selectPage 方法:BaseMapper 提供的分页查询方法,传入 Page 分页对象和 LambdaQueryWrapper 条件构造器,自动执行分页查询,返回包含分页信息和数据的 Page 对象。
java
package com.example.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dto.StudentQueryDTO;
import com.example.entity.Student;
import com.example.mapper.StudentMapper;
import com.example.service.StudentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service // 标记为 Service 组件,Spring 自动管理
@RequiredArgsConstructor // Lombok 注解,自动生成构造器,实现依赖注入
public class StudentServiceImpl implements StudentService {
// 注入 StudentMapper,final 修饰,确保不可变
private final StudentMapper studentMapper;
@Override
public Page<Student> queryStudentByPage(StudentQueryDTO dto) {
// 1. 构建分页对象:传入页码(pageNum)和每页条数(pageSize)
Page<Student> page = new Page<>(dto.getPageNum(), dto.getPageSize());
// 2. 构建多条件查询构造器(LambdaQueryWrapper 类型安全,避免字段名写错)
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
// 姓名模糊查询:姓名不为空时,拼接 like 条件(%name%)
wrapper.like(StringUtils.hasText(dto.getName()), Student::getName, dto.getName());
// 班级精确查询:班级不为空时,拼接 eq 条件
wrapper.eq(StringUtils.hasText(dto.getClassName()), Student::getClassName, dto.getClassName());
// 最低分数查询:minScore 不为 null 时,拼接 >= 条件
wrapper.ge(dto.getMinScore() != null, Student::getScore, dto.getMinScore());
// 最高分数查询:maxScore 不为 null 时,拼接 <= 条件
wrapper.le(dto.getMaxScore() != null, Student::getScore, dto.getMaxScore());
// 3. 执行分页查询:调用 BaseMapper 的 selectPage 方法,自动分页
return studentMapper.selectPage(page, wrapper);
}
}
3.5 Controller 层(表现层)
知识点1:@RestController 注解:组合注解,等价于 @Controller + @ResponseBody,标记当前类为 REST 接口控制器,所有方法的返回值会自动转为 JSON 格式,返回给前端(无需手动处理 JSON 转换)。
知识点2:@RequestMapping("/student"):类级别的请求路径映射,所有该类下的接口都会以 /student 为前缀,简化接口路径编写。
知识点3:@PostMapping("/query/page"):方法级别的请求路径映射,指定该方法接收 POST 请求,路径为 /student/query/page,适合接收复杂的请求参数(如多条件查询参数)。
知识点4:@RequestBody 注解:用于接收前端传递的 JSON 格式请求体,自动将 JSON 数据转换为 StudentQueryDTO 对象(需保证 JSON 字段名与 DTO 字段名一致)。
知识点5:依赖注入 Service:通过 @RequiredArgsConstructor 注入 StudentService,调用 Service 层方法处理业务逻辑,Controller 层不直接处理业务,仅负责请求接收和结果返回。
java
package com.example.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dto.StudentQueryDTO;
import com.example.entity.Student;
import com.example.service.StudentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // 标记为 REST 控制器,返回 JSON 格式数据
@RequestMapping("/student") // 类级路径前缀:所有接口都以 /student 开头
@RequiredArgsConstructor // 构造器注入 Service
public class StudentController {
// 注入 StudentService,调用业务逻辑方法
private final StudentService studentService;
// 分页+多条件查询接口:POST 请求,接收 JSON 格式参数
@PostMapping("/query/page")
public Page<Student> getStudentByPage(@RequestBody StudentQueryDTO dto) {
// 调用 Service 层方法,返回分页结果,自动转为 JSON 给前端
return studentService.queryStudentByPage(dto);
}
}
3.6 Config 层(配置层)- 分页插件配置
知识点1:@Configuration 注解:标记当前类为 Spring 配置类,Spring 会自动扫描该类,加载其中的 Bean 配置。
知识点2:MyBatis-Plus 分页插件:Spring Boot 3.x 中,MyBatis-Plus 分页插件需要手动配置(注入 MybatisPlusInterceptor),否则分页查询不生效(只会查询所有数据,不会分页)。
知识点3:PaginationInnerInterceptor:MyBatis-Plus 内置的分页拦截器,传入 DbType.MYSQL 指定数据库类型,自动适配 MySQL 的分页语法(limit 语句)。
java
package com.example.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration // 标记为 Spring 配置类
public class MyBatisPlusConfig {
// 注入 MyBatis-Plus 拦截器,添加分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加 MySQL 分页拦截器,确保分页生效
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
3.7 启动类(Application.java)
知识点1:@SpringBootApplication 注解:Spring Boot 核心注解,组合了 @Configuration、@EnableAutoConfiguration、@ComponentScan 三个注解,用于标记项目启动类,自动配置 Spring 上下文、扫描组件。
知识点2:@MapperScan("com.example.mapper"):指定 MyBatis Mapper 接口的扫描路径,Spring 会自动扫描该路径下的所有 @Mapper 接口,生成代理对象,否则 Mapper 接口无法被注入(会报 NoSuchBeanDefinitionException 异常)。
知识点3:main 方法:项目入口,通过 SpringApplication.run(Application.class, args) 启动 Spring Boot 项目,自动加载所有配置和组件。
java
package com.example;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 标记为 Spring Boot 启动类,自动配置
@MapperScan("com.example.mapper") // 扫描 Mapper 接口,确保注入成功
public class Application {
public static void main(String[] args) {
// 启动 Spring Boot 项目
SpringApplication.run(Application.class, args);
}
}
四、接口测试知识点
知识点1:请求方式:分页+多条件查询接口使用 POST 请求,因为请求参数较多(多条件+分页),POST 请求适合传递复杂参数(JSON 格式),GET 请求适合传递简单参数(路径参数、请求参数)。
知识点2:请求地址 :http://localhost:8080/student/query/page(localhost 为本地服务器地址,8080 为 Spring Boot 默认端口,可在 application.yml 中修改)。
知识点3:请求体(JSON 格式):参数与 StudentQueryDTO 字段对应,可选参数可省略(如不传递 name,即不按姓名查询)。
json
{
"name": "张", // 可选:姓名模糊查询
"className": "高一(1)班", // 可选:班级精确查询
"minScore": 60, // 可选:最低分数
"maxScore": 100, // 可选:最高分数
"pageNum": 1, // 可选:页码(默认1)
"pageSize": 10 // 可选:每页条数(默认10)
}
知识点4:返回结果:Page<Student> 自动转为 JSON 格式,包含以下核心字段:
-
records:当前页的学生列表(实体类 Student 对应的 JSON 数据)。
-
total:总条数(符合条件的所有学生数量)。
-
size:每页条数。
-
current:当前页码。
-
pages:总页数(自动计算:total / size,向上取整)。
五、补充知识点(VO 层说明)
知识点1:VO 层作用:VO(View Object)视图对象,用于后端返回给前端的展示数据,与 DTO 相反:DTO 是"前端传入后端",VO 是"后端返回前端"。
知识点2:为什么需要 VO 层?:
-
安全:Entity 可能包含敏感字段(如 idNo 身份证号),VO 可只返回前端需要的字段(如 name、className、score),隐藏敏感信息。
-
灵活:可在 VO 中添加前端需要的计算字段(如 scoreLevel:优秀/及格/不及格),Entity 中无需包含该字段。
知识点3:使用场景:小型项目可直接用 Entity 返回前端(简化开发);大型项目、生产环境建议使用 VO 层,规范数据返回,提升安全性。
示例 VO(StudentVO.java):
java
package com.example.vo;
import lombok.Data;
@Data
public class StudentVO {
private String name; // 前端需要的姓名
private String className; // 前端需要的班级
private Integer score; // 前端需要的成绩
private String scoreLevel; // 计算字段:优秀(90+)、及格(60-89)、不及格(<60)
}
六、常见问题 & 注意事项
-
分页不生效:未配置 MyBatis-Plus 分页插件(MyBatisPlusConfig),或插件配置错误(如未指定 DbType)。
-
Mapper 注入失败:未添加 @Mapper 注解,或 @MapperScan 扫描路径错误。
-
版本兼容报错:Spring Boot 3.x 未使用 mybatis-plus-spring-boot3-starter,改用了旧版 mybatis-plus-boot-starter。
-
条件查询不生效:条件构造器中 condition 参数判断错误(如用 StringUtils.isEmpty() 导致空字符串也拼接条件)。
-
JSON 转换失败:前端传递的 JSON 字段名与 DTO 字段名不一致,或字段类型不匹配(如前端传字符串,DTO 用 Integer 接收)。
(注:文档部分内容可能由 AI 生成)