SpringBoot学生成绩管理系统实战:从零搭建完整Java Web项目
每到期末课程设计、大作业、毕业设计接踵而至你是不是也曾在深夜对着电脑屏幕为如何快速搭建一个“像样”的Java Web项目而发愁想用SpringBoot却不知从何下手想实现增删改查却总被各种配置和依赖搞得焦头烂额好不容易找到一份源码却发现要么版本老旧要么文档缺失跑都跑不起来。今天这篇文章就是为你准备的“期末救星”。我们不谈空泛的理论不堆砌复杂的架构图而是直接带你手把手、保姆级地完成一个基于SpringBoot的学生成绩管理系统。这个项目麻雀虽小五脏俱全涵盖了从环境搭建、数据库设计、后端开发到前端页面交互的完整流程。更重要的是我会为你剖析在实现“增删改查”这个看似简单的需求背后新手最容易踩的五个技术深坑并提供完整的源码、数据库脚本和项目文档。无论你是正在为课设、期末大作业寻找参考项目的学生还是希望快速上手SpringBoot全栈开发的入门者这篇文章都将提供一条清晰、可落地的实践路径。我们不仅会“跑通”项目更会理解每一步“为什么”要这么做让你真正掌握一个SpringBoot项目的骨架并能举一反三应用到自己的项目中。1. 为什么选择“学生成绩管理系统”作为SpringBoot入门项目在众多练手项目中“学生成绩管理系统”之所以经久不衰成为课程设计的“常客”背后有深刻的合理性。它完美匹配了SpringBoot技术栈的典型应用场景和初学者的学习曲线。首先业务场景清晰且贴近实际。学生、课程、成绩、教师、班级这些实体和它们之间的关系如一个学生选修多门课程一门课程有多个成绩是天然的数据模型非常适合用来练习数据库设计和ORM映射。你不必花费大量精力去理解复杂的业务逻辑可以更专注于技术实现本身。其次功能需求完整且层次分明。核心的“增删改查”CRUD操作覆盖了后端开发的基石。在此基础上你可以自然地延伸出用户登录/权限控制区分管理员、教师、学生、数据统计分析计算平均分、排名、文件导入导出等进阶功能。这为你提供了一个从简单到复杂、逐步迭代的完美学习路径。最关键的是技术栈组合经典且实用。一个标准的SpringBoot成绩管理系统通常会整合以下技术这正是当前企业级Java Web开发的主流选择SpringBoot 2.x: 快速构建、自动配置告别繁琐的XML。Spring MVC: 处理Web请求和响应的核心框架。MyBatis-Plus: 极大简化数据库操作的ORM框架是MyBatis的增强工具。Thymeleaf: 服务端模板引擎易于与SpringBoot集成适合前后端不分离的入门项目。MySQL: 最流行的开源关系型数据库。Maven: 项目构建和依赖管理工具。Bootstrap/Ajax: 用于快速构建美观的前端界面和实现局部刷新。通过完成这个项目你不仅能学会单个技术的使用更能掌握如何将这些技术有机地组合在一起形成一个可工作的系统。这远比孤立地学习某个注解或API更有价值。2. 项目核心功能与系统设计在动手编码之前我们必须明确要构建什么。一个完整的学生成绩管理系统其核心是围绕“成绩”这一核心数据对“学生”和“课程”进行管理。2.1 核心功能模块系统管理用户登录/注销不同角色如管理员、教师拥有不同权限。权限控制例如只有管理员可以管理学生和课程信息教师可以录入和修改所授课程的成绩学生只能查看自己的成绩。学生信息管理对学生基本信息的增、删、改、查。课程信息管理对课程基本信息的增、删、改、查。成绩管理核心成绩录入教师为指定课程下的学生录入或修改成绩。成绩查询支持按学生、课程、班级等多维度查询。成绩统计分析计算个人平均分、课程平均分、排名等。数据报表以图表或表格形式展示统计分析结果。2.2 数据库设计ER图核心思想数据库设计是项目的基石。一个糟糕的设计会让后续开发举步维艰。我们的系统主要包含以下几张表用户表 (sys_user)存储登录账号、密码加密、角色、姓名等。学生表 (student)存储学号、姓名、性别、所属班级、联系方式等。与用户表可关联一个学生对应一个登录账号。课程表 (course)存储课程编号、课程名称、学分、授课教师等。成绩表 (score)这是核心关联表。存储学生ID、课程ID、成绩。它建立了学生和课程之间的多对多关系一个学生可以选多门课一门课可以被多个学生选。设计要点主键通常使用自增ID或雪花算法ID业务编号如学号、课程编号可作为唯一索引。密码字段必须加密存储推荐使用BCryptPasswordEncoder。表之间通过外键关联但在实际开发中为了灵活性有时只在逻辑上关联不在数据库层面建立外键约束。考虑添加create_time,update_time等审计字段便于追踪数据变化。3. 开发环境与工具准备工欲善其事必先利其器。以下是完成本项目所需的环境和工具清单。请务必确保版本兼容这是避免后续各种诡异错误的第一步。工具/环境推荐版本说明JDK1.8 或 11SpringBoot 2.x 对 JDK 8 兼容性最好JDK 11 也是长期支持版本。IDEIntelliJ IDEA社区版即可对SpringBoot支持极佳。Eclipse STS插件也可。项目构建Maven 3.6管理项目依赖的生命线。数据库MySQL 5.7 或 8.0两者皆可注意连接驱动版本的匹配。数据库工具Navicat, DBeaver 或 IDEA自带用于连接数据库、执行SQL脚本、查看数据。浏览器Chrome 或 Edge用于测试前端页面。环境验证步骤打开终端CMD或PowerShell输入java -version和mvn -v确认版本信息正确输出。启动MySQL服务并用客户端工具成功连接。在IDEA中新建一个SpringBoot项目进行测试确保能正常启动。4. 从零开始创建SpringBoot项目与基础配置我们将使用IntelliJ IDEA的Spring Initializr来快速生成项目骨架这是最标准、最推荐的方式。4.1 使用 Spring Initializr 创建项目打开IDEA选择File - New - Project。左侧选择Spring Initializr选择合适的JDK版本。填写项目元数据MetadataGroup:com.example(示例可改为自己的域名倒写如com.yourname)Artifact:student-score-systemType:MavenJava Version:8或11Packaging:Jar(SpringBoot推荐)在Dependencies页面添加我们需要的起步依赖Spring Web(构建Web应用包含Spring MVC)Thymeleaf(模板引擎)MyBatis Framework(或直接搜索MyBatis Plus但Initializr可能没有我们稍后手动添加)MySQL Driver(数据库驱动)Lombok(简化Java Bean代码强烈推荐)点击FinishIDEA会自动下载初始依赖并创建项目。4.2 手动添加 MyBatis-Plus 依赖Spring Initializr可能没有MyBatis-Plus的选项我们需要手动在pom.xml中添加。MyBatis-Plus是对MyBatis的增强提供了通用的Mapper和Service能极大减少CRUD代码。打开项目根目录下的pom.xml文件在dependencies节点内添加!-- MyBatis-Plus 起步依赖 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version !-- 请查看官网使用最新稳定版 -- /dependency !-- 代码生成器可选用于快速生成实体、Mapper、Service代码 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.3.1/version scopetest/scope /dependency然后在IDEA右侧Maven工具栏点击刷新按钮下载新添加的依赖。4.3 核心配置文件详解SpringBoot的配置主要在src/main/resources/application.properties(或application.yml) 中。我们使用yml格式它层次更清晰。将application.properties重命名为application.yml并写入以下配置# 服务器端口 server: port: 8080 # 应用名称 spring: application: name: student-score-system # 数据源配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/student_score_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root # 你的数据库用户名 password: 123456 # 你的数据库密码 # Thymeleaf 配置 thymeleaf: cache: false # 开发时关闭缓存修改页面立即生效 mode: HTML encoding: UTF-8 # MyBatis-Plus 配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL语句便于调试 global-config: db-config: id-type: auto # 主键策略数据库自增 logic-delete-field: deleted # 全局逻辑删除字段名若需要 logic-delete-value: 1 # 逻辑已删除值 logic-not-delete-value: 0 # 逻辑未删除值 mapper-locations: classpath:mapper/*.xml # XML映射文件位置如果使用注解则不需要关键配置解释datasource.url中的serverTimezoneAsia/Shanghai是解决MySQL 8.0时区问题的关键否则可能连接失败。mybatis-plus.configuration.log-impl用于在控制台输出执行的SQL开发阶段极其有用但生产环境应关闭。id-type: auto表示使用数据库自增主键你也可以设置为assign_id(雪花算法ID)。5. 数据库建表与实体类映射5.1 执行SQL建表脚本在MySQL中创建一个名为student_score_db的数据库然后执行以下SQL脚本CREATE DATABASE IF NOT EXISTS student_score_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE student_score_db; -- 用户表简单示例实际可能更复杂 CREATE TABLE sys_user ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 加密后的密码, real_name varchar(50) DEFAULT NULL COMMENT 真实姓名, role varchar(20) NOT NULL DEFAULT student COMMENT 角色admin, teacher, student, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表; -- 学生表 CREATE TABLE student ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, student_no varchar(20) NOT NULL COMMENT 学号, name varchar(50) NOT NULL COMMENT 姓名, gender tinyint(1) DEFAULT 0 COMMENT 性别0-男1-女, class_name varchar(50) DEFAULT NULL COMMENT 班级名称, phone varchar(20) DEFAULT NULL COMMENT 联系电话, user_id bigint(20) DEFAULT NULL COMMENT 关联的用户ID, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_student_no (student_no), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生信息表; -- 课程表 CREATE TABLE course ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, course_no varchar(20) NOT NULL COMMENT 课程编号, course_name varchar(100) NOT NULL COMMENT 课程名称, credit decimal(3,1) DEFAULT 2.0 COMMENT 学分, teacher_name varchar(50) DEFAULT NULL COMMENT 授课教师, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_course_no (course_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT课程信息表; -- 成绩表核心关联表 CREATE TABLE score ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, student_id bigint(20) NOT NULL COMMENT 学生ID, course_id bigint(20) NOT NULL COMMENT 课程ID, score decimal(5,2) DEFAULT NULL COMMENT 成绩, exam_time varchar(20) DEFAULT NULL COMMENT 考试时间如2023-2024-1, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_student_course (student_id,course_id), -- 防止重复录入同一学生同一课程的成绩 KEY idx_student_id (student_id), KEY idx_course_id (course_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生成绩表;5.2 使用Lombok创建实体类(Entity)在src/main/java/com/example/studentscoresystem/entity包下创建对应的Java实体类。使用Lombok注解可以省去getter/setter/toString等样板代码。Student.javapackage com.example.studentscoresystem.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.time.LocalDateTime; Data TableName(student) // 指定对应的数据库表名 public class Student { TableId(type IdType.AUTO) // 主键自增 private Long id; private String studentNo; // 学号驼峰命名对应数据库下划线 student_no private String name; private Integer gender; // 0-男1-女 private String className; private String phone; private Long userId; private LocalDateTime createTime; private LocalDateTime updateTime; }Course.java和Score.java的创建方式类似。注意Score实体中包含了studentId和courseId作为外键关联。关键点Data Lombok注解自动生成getter, setter, toString, equals, hashCode方法。TableName MyBatis-Plus注解指定实体对应的数据库表名。TableId 指定主键字段和生成策略。字段名使用驼峰命名如studentNoMyBatis-Plus默认会将其映射到数据库的下划线命名student_no无需额外配置。6. 使用MyBatis-Plus实现高效的数据访问层MyBatis-Plus的核心优势在于其通用Mapper和通用Service对于单表操作你几乎不需要写任何SQL。6.1 创建Mapper接口在mapper包下创建接口继承MyBatis-Plus提供的BaseMapper。StudentMapper.javapackage com.example.studentscoresystem.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.studentscoresystem.entity.Student; import org.apache.ibatis.annotations.Mapper; Mapper // 让Spring容器管理此Mapper public interface StudentMapper extends BaseMapperStudent { // 无需编写任何方法BaseMapper已提供了insert, deleteById, updateById, selectById, selectList等全套CRUD方法 }CourseMapper和ScoreMapper的创建方式完全相同。6.2 创建Service接口和实现类虽然可以直接在Controller中调用Mapper但良好的分层架构要求有Service层处理业务逻辑。StudentService.java (接口)package com.example.studentscoresystem.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.studentscoresystem.entity.Student; import java.util.List; public interface StudentService extends IServiceStudent { // 可以在此定义复杂的业务查询方法简单的CRUD已由IService提供 ListStudent getStudentsByClassName(String className); }StudentServiceImpl.java (实现类)package com.example.studentscoresystem.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.studentscoresystem.entity.Student; import com.example.studentscoresystem.mapper.StudentMapper; import com.example.studentscoresystem.service.StudentService; import org.springframework.stereotype.Service; import java.util.List; Service // 声明为Spring的Service组件 public class StudentServiceImpl extends ServiceImplStudentMapper, Student implements StudentService { Override public ListStudent getStudentsByClassName(String className) { // 使用MyBatis-Plus的QueryWrapper构建查询条件 QueryWrapperStudent queryWrapper new QueryWrapper(); queryWrapper.eq(class_name, className); // 相当于 SQL: where class_name #{className} queryWrapper.orderByDesc(create_time); // 按创建时间倒序 return this.list(queryWrapper); // 执行查询 } }MyBatis-Plus的强大之处ServiceImplM, T已经实现了IService中定义的所有通用方法如save,removeById,updateById,getById,list等。QueryWrapper是构建动态查询条件的利器通过链式调用可以轻松组合eq(等于)、like(模糊)、gt(大于)、orderBy(排序)等条件完全避免手写SQL字符串。7. 控制器(Controller)与页面(Thymeleaf)交互这是连接前端请求和后端逻辑的桥梁。我们将实现一个简单的学生信息管理功能。7.1 学生控制器(StudentController)package com.example.studentscoresystem.controller; import com.example.studentscoresystem.entity.Student; import com.example.studentscoresystem.service.StudentService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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(/student) // 所有请求路径以 /student 开头 public class StudentController { Autowired private StudentService studentService; // 分页查询学生列表 GetMapping(/list) public String listStudents(RequestParam(value pageNum, defaultValue 1) Integer pageNum, RequestParam(value pageSize, defaultValue 10) Integer pageSize, Model model) { // 1. 创建分页对象 PageStudent page new Page(pageNum, pageSize); // 2. 创建查询条件这里查询所有可以添加name等过滤条件 QueryWrapperStudent queryWrapper new QueryWrapper(); queryWrapper.orderByDesc(create_time); // 3. 执行分页查询 PageStudent studentPage studentService.page(page, queryWrapper); // 4. 将数据放入Model供Thymeleaf页面渲染 model.addAttribute(pageInfo, studentPage); return student/list; // 返回视图名称对应 src/main/resources/templates/student/list.html } // 跳转到新增学生页面 GetMapping(/toAdd) public String toAdd() { return student/add; } // 处理新增学生请求 PostMapping(/add) public String addStudent(Student student) { // Spring MVC自动将表单参数绑定到Student对象 studentService.save(student); return redirect:/student/list; // 重定向到列表页防止表单重复提交 } // 跳转到编辑页面 GetMapping(/toEdit/{id}) public String toEdit(PathVariable Long id, Model model) { Student student studentService.getById(id); model.addAttribute(student, student); return student/edit; } // 处理更新学生请求 PostMapping(/update) public String updateStudent(Student student) { studentService.updateById(student); return redirect:/student/list; } // 处理删除请求 GetMapping(/delete/{id}) public String deleteStudent(PathVariable Long id) { studentService.removeById(id); return redirect:/student/list; } }7.2 Thymeleaf页面示例 (student/list.html)在src/main/resources/templates/student/目录下创建list.html。!DOCTYPE html html langzh xmlns:thhttp://www.thymeleaf.org head meta charsetUTF-8 title学生列表/title !-- 引入Bootstrap CSS -- link hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.1.3/dist/css/bootstrap.min.css relstylesheet /head body div classcontainer mt-4 h2学生信息管理/h2 a th:href{/student/toAdd} classbtn btn-primary mb-3新增学生/a table classtable table-bordered table-hover thead classtable-light tr thID/th th学号/th th姓名/th th性别/th th班级/th th电话/th th操作/th /tr /thead tbody !-- Thymeleaf 循环渲染每一条学生数据 -- tr th:eachstudent : ${pageInfo.records} td th:text${student.id}/td td th:text${student.studentNo}/td td th:text${student.name}/td td span th:text${student.gender 0} ? 男 : 女/span /td td th:text${student.className}/td td th:text${student.phone}/td td a th:href{/student/toEdit/{id}(id${student.id})} classbtn btn-sm btn-warning编辑/a a th:href{/student/delete/{id}(id${student.id})} classbtn btn-sm btn-danger onclickreturn confirm(确定删除吗)删除/a /td /tr /tbody /table !-- 分页组件 -- nav ul classpagination li classpage-item th:classappend${pageInfo.current 1} ? disabled : a classpage-link th:href{/student/list(pageNum${pageInfo.current - 1})}上一页/a /li !-- 遍历页码这里简化显示实际项目可能需要更复杂逻辑 -- li th:eachpageNum : ${#numbers.sequence(1, pageInfo.pages)} classpage-item th:classappend${pageInfo.current pageNum} ? active : a classpage-link th:href{/student/list(pageNum${pageNum})} th:text${pageNum}/a /li li classpage-item th:classappend${pageInfo.current pageInfo.pages} ? disabled : a classpage-link th:href{/student/list(pageNum${pageInfo.current 1})}下一页/a /li /ul div当前第 span th:text${pageInfo.current}/span 页共 span th:text${pageInfo.pages}/span 页总计 span th:text${pageInfo.total}/span 条记录/div /nav /div !-- 引入Bootstrap JS -- script srchttps://cdn.jsdelivr.net/npm/bootstrap5.1.3/dist/js/bootstrap.bundle.min.js/script /body /htmlThymeleaf关键语法th:href{...}: 生成正确的URL支持路径参数。th:text${...}: 将表达式结果作为文本显示。th:eachitem : ${list}: 循环遍历集合。th:if,th:unless: 条件判断。#numbers.sequence(): 生成数字序列用于分页。add.html和edit.html是包含表单的页面用于提交数据其结构与list.html类似主要包含form标签和th:object绑定。8. 项目运行与效果验证8.1 启动项目找到主启动类通常位于src/main/java/com/example/studentscoresystem/StudentScoreSystemApplication.java。package com.example.studentscoresystem; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication public class StudentScoreSystemApplication { public static void main(String[] args) { SpringApplication.run(StudentScoreSystemApplication.class, args); } }右键运行这个类的main方法。观察控制台日志看到类似以下信息表示启动成功Started StudentScoreSystemApplication in 5.123 seconds (JVM running for 6.456) Tomcat started on port(s): 8080 (http) with context path 8.2 功能测试打开浏览器访问http://localhost:8080/student/list。你应该能看到一个空的学生列表表格因为数据库还没有数据和“新增学生”按钮。点击“新增学生”填写表单并提交。提交后页面跳转回列表页你新增的学生信息应该显示在表格中。尝试点击“编辑”和“删除”按钮验证功能是否正常。8.3 验证数据持久化使用数据库客户端工具如Navicat连接你的MySQL数据库查看student_score_db库中的student表确认数据已被正确插入、更新或删除。9. 常见问题与排查思路新手必看在实现上述流程时你几乎一定会遇到下面这些问题。提前了解可以节省大量排查时间。问题现象可能原因排查方式解决方案启动报错Failed to configure a DataSource1. 数据库连接配置错误URL、用户名、密码。2. MySQL服务未启动。3. 数据库驱动版本不匹配。1. 检查application.yml中的spring.datasource配置。2. 在命令行或服务中确认MySQL已运行。3. 检查pom.xml中MySQL驱动版本与安装的MySQL版本是否兼容8.0推荐使用mysql-connector-java8.x。1. 修正配置信息。2. 启动MySQL服务。3. 调整驱动版本或添加连接参数serverTimezone。访问页面报404错误1. 控制器(Controller)的请求映射(RequestMapping)路径写错。2. 页面文件没有放在resources/templates目录下或路径不对。3. 没有添加Controller注解。1. 检查浏览器地址栏URL与Controller中定义的路径是否一致。2. 检查Thymeleaf模板文件的位置和名称。3. 检查Controller类是否有Controller或RestController注解。1. 修正路径。2. 将HTML文件移动到正确目录。3. 添加正确的注解。页面能访问但数据显示为${...}Thymeleaf语法未被解析。1. 检查HTML文件开头是否引入了Thymeleaf命名空间xmlns:thhttp://www.thymeleaf.org。2. 检查是否错误地使用了RestController它返回JSON不解析视图。1. 确保HTML文件头正确。2. 返回页面的方法所在类使用Controller。插入/更新数据时字段值为null1. 前端表单(input)的name属性与实体类(Entity)字段名不匹配。2. 实体类字段与数据库表列名映射失败驼峰转下划线问题。1. 检查表单name属性如input namestudentNo。2. 查看MyBatis-Plus日志输出的SQL看插入的字段有哪些。1. 使表单name与实体类字段名一致。2. 确认数据库列名是下划线格式实体类字段是驼峰格式。MyBatis-Plus默认支持此映射。也可使用TableField(column_name)注解指定。控制台不打印SQL日志未开启MyBatis-Plus的SQL日志。检查application.yml中mybatis-plus.configuration.log-impl配置。确保配置为org.apache.ibatis.logging.stdout.StdOutImpl。删除或查询不到数据1. 逻辑删除配置冲突。2. 查询条件构造错误。1. 检查实体类中是否有标记了TableLogic的字段并检查全局逻辑删除配置。2. 打印QueryWrapper对象或查看日志中的SQL。1. 如果不使用逻辑删除请移除相关配置和注解。2. 使用queryWrapper.getSqlSegment()打印条件或开启SQL日志调试。10. 项目扩展与最佳实践建议完成基础CRUD只是第一步。要让这个项目更完整、更健壮你可以从以下方向进行扩展这也是面试和实际项目中常被考察的点。10.1 功能扩展方向用户认证与授权集成Spring Security或Shiro实现基于角色的页面访问控制和API权限拦截。成绩管理模块实现成绩的批量导入使用EasyExcel或Apache POI处理Excel、复杂查询多表关联查询如查询学生姓名、课程名称和成绩和统计分析使用SQL的GROUP BY或Java Stream API。前端交互增强使用Ajax实现无刷新删除、搜索和分页提升用户体验。可以结合jQuery或原生Fetch API。数据验证在实体类中使用JSR-303注解如NotBlank,Email,Range进行后端数据校验并在前端使用JavaScript进行初步校验。异常统一处理使用ControllerAdvice和ExceptionHandler全局处理系统异常返回友好的错误页面或JSON信息。日志记录使用SLF4J Logback记录用户操作日志和系统运行日志。10.2 工程化最佳实践分层清晰严格遵循Controller - Service - Mapper的分层架构每层职责单一。使用DTO和VO不要直接用Entity接收前端请求或返回给前端。创建StudentDTO用于接收新增/修改请求创建StudentVO用于返回列表数据这样可以隐藏不必要的字段如密码password也可以组合多个Entity的数据。接口版本管理如果提供RESTful API可以考虑在URL中加入版本号如/api/v1/student。配置分离将数据库密码等敏感信息从application.yml移到application-dev.yml(开发环境) 和application-prod.yml(生产环境)并通过Spring Profile激活。单元测试为Service层和Controller层编写JUnit单元测试保证核心逻辑的正确性。API文档集成Swagger或Knife4j自动生成在线API文档便于前后端协作。10.3 部署与打包使用mvn clean package命令将项目打包成可执行的JAR文件。在生产服务器上只需安装JDK通过java -jar your-project.jar即可运行。考虑使用Docker容器化部署进一步简化环境依赖。这个基于SpringBoot的学生成绩管理系统项目就像一把钥匙为你打开了Java全栈开发的大门。它串联起了从数据库设计、后端逻辑到前端展示的完整链条。当你成功运行起这个系统并理解了每一行配置、每一个注解背后的意义时你已经跨越了从“知道”到“做到”的最关键一步。项目的完整源码、详细的SQL脚本以及更结构化的项目文档你可以根据上述步骤自行构建这也是学习的一部分。记住看懂和写出之间隔着一条实践的鸿沟。最好的学习方式就是马上打开你的IDE从创建一个Spring Initializr项目开始亲手敲下每一行代码解决每一个报错。当你把这个项目完全消化并能根据自己的想法添加新功能时SpringBoot对你而言就不再是陌生的框架而是一个得心应手的工具。