学生选课成绩管理系统:Java Swing + MySQL 课程设计完整实现与避坑指南 简介这套基于 Java Swing 与 MySQL 构建的学生选课及成绩管理系统适合正在完成课程设计、毕业设计或初学桌面应用开发的学习者。项目包含学生信息管理、课程管理、选课与成绩查询等核心模块覆盖从登录认证到数据增删改查的常见开发流程可作为完整参考方案直接借鉴或二次开发。资源包共 53 个文件以 Java 源码、界面运行截图和 XML 配置文件为主附有数据库 SQL 脚本、E-R 图及 MySQL 驱动 jar大小 8.63MB便于对照界面与代码梳理系统结构。内置管理员、教师、学生三类账号且在 JdbcConfig 中提供了明确的数据库连接配置入口可快速部署测试。资源已有 219 人学习适合希望掌握 Swing 界面编程与 MySQL 实操联动的入门及进阶用户。1. 选课系统课程设计的正确打开方式从登录到成绩查询的完整闭环基于 Java Swing MySQL 的学生选课及成绩管理系统课程设计是很多计算机专业学生在课程设计和毕业设计阶段绕不开的桌面项目。这套资源把管理员、教师、学生三种角色的登录入口、选课业务、成绩录入与查询、界面截图和数据库脚本全部打包在一起解决的不只是「跑通代码」而是把 Java 基础里的 JDBC 连接、Swing 事件监听、MySQL 表设计和角色权限串成一个完整闭环。适合两类人一类是正在做课程设计或大作业的学生需要一份能直接复现的完整工程另一类是刚把 Java 基础过完的初学者想通过真实项目理解桌面应用怎么跟数据库打交道。我拆这类工程时最关注三件事能不能一次跑通、数据库初始化是否顺畅、界面和业务逻辑是否对得上。下面就从这三条线展开把每个环节的参数和坑位都写清楚。2. 系统架构与数据库设计三张核心表和角色权限的划分2.1 登录角色与权限设计的三个入口这套资源的登录界面认三组账号管理员 admin/123 进入学生信息管理和学生课程管理教师 tch/123 进入成绩录入和成绩管理学生 stu/123 进入选课和成绩查询。设计上最值得学习的不是具体代码而是「一个入口、三种路由」的权限划分思路——登录成功后不是简单跳转主界面而是根据角色拼接不同的菜单和操作按钮这是 Swing 桌面项目里最容易做乱的地方。从配套截图能看到管理员界面里有学生信息管理、课程管理、成绩管理多个 Tab 页教师界面侧重成绩录入和修改学生界面则只有选课和查询。权限粒度不需要做到 Web 项目那种细粒度拦截但「看不到不相关按钮」是底线。资源里 README.md 和三张界面截图对照着看能很快找到每个功能模块对应的界面类。实现上一般有两种做法一种是把角色写死在一个标记变量里登录成功后用 if/switch 决定显示哪些页面另一种是定义 BaseFrame 基类子类按角色覆写菜单。课程设计阶段用第一种就够了重点是让登录态贯穿整个会话别在选课界面里还去调用教师才能用的成绩管理方法。2.2 核心数据表结构与 E-R 图对照项目里有一张数据库 E-R 图把学生、课程、成绩的实体关系画得很直观。对照 E-R 图梳理表结构这类系统最少需要五张表学生表、教师表、课程表、选课表、成绩表。选课表是学生和课程的多对多关系中间表成绩表则同时关联学生和课程。这样设计的好处是学生选课和教师录成绩都落在关系表上不会在学生表里塞一堆冗余的课程字段。表名关键字段说明studentid, sno, name, gender, class_name, password学生账号sno 做登录名teacherid, tno, name, password教师账号tno 做登录名courseid, cno, name, credit, teacher_id课程基本信息teacher_id 关联教师student_courseid, student_id, course_id, selected_time选课中间表记录选课时间和关系scoreid, student_id, course_id, score, remark成绩表一个学生一门课一条记录E-R 图里学生和课程之间是典型的多对多student_course 就是那个中间表score 表把课程和成绩关联起来查询时通过 student_id 和 course_id 做连接就能拿到一张带学号、姓名、课程名、学分、成绩的完整视图。初始化账号里的 stu / tch 分别对应 student.sno 和 teacher.tnoadmin 一般单独写在管理员表或者直接硬编码在代码常量里。2.3 为什么选 Swing MySQL 而不是 Web 技术栈现在很多课程设计默认选 Spring Boot Vue但这份资源用 Swing MySQL反而是更贴近 Java 基础课知识覆盖面的组合。Swing 是 JDK 自带 GUI 框架不依赖额外前端工程JDBC 直连比 MyBatis、Spring Data JPA 少了一层封装登录校验、预编译 SQL、事务提交都能看到原生写法。对正在复习 Java 基础的人来说把 Swing 事件监听和 PreparedStatement 弄明白比背一堆注解强。MySQL 8.0.36 是目前课程设计环境里最常见的数据库版本项目里 lib 目录直接放了 mysql-connector-j-8.3.0.jar说明作者已经处理过驱动依赖不用自己满网找 jar 包。配套的 Navicat 16 图形化工具主要用来导入 SQL 脚本和核对数据比命令行直观很多。这套技术栈的代价是界面美观度不如 Web但课程设计答辩更看重功能完整度和你对代码的讲解深度桌面版反而容易把逻辑讲清楚。3. 环境搭建与数据库初始化JDK 1.8 MySQL 8.0 的配置细节3.1 开发工具版本对齐先看版本再看代码打开项目前先对齐开发工具版本这是减少翻车的第一步。资源要求的组合是 JDK 1.8 IDEA MySQL 8.0.36 Navicat 16数据库连接驱动用 lib 目录下的 mysql-connector-j-8.3.0.jar。这个组合的关键点是驱动 8.x 系列兼容 JDK 1.8而 MySQL 8.0 的默认认证插件是 caching_sha2_password老版本的 mysql-connector-java 5.x 连不上所以必须用配套的 8.x 驱动。工具版本用途JDK1.8Java 编译和运行环境IDEA任意较新版本编译器和项目管理MySQL8.0.36业务数据存储Navicat16数据库图形化管理mysql-connector-j8.3.0JDBC 驱动位于 lib 目录如果你的机器装的是 JDK 11 或 17代码大概率也能跑因为项目没有用到 JDK 1.8 之后移除的 API。但建议还是按原环境走减少变量。MySQL 版本如果本机是 5.7连接 URL 里的参数要改一下这个问题在第 5 章避坑里会详细说。3.2 导入 SQL 脚本与初始化默认账号数据库初始化是这套资源能否一次跑起来的关键。项目里 SQL 文件在 src/resources/sql/ 目录下打开这个目录看名字就能确认是建库脚本还是带数据的完整脚本。常见做法是直接用 Navicat 连接 MySQL 后右键对应数据库运行 SQL 文件也可以用命令行导入。mysql -u root -p src/resources/sql/student_course.sql执行后输入 MySQL 的 root 密码脚本会自动建库建表并把三组账号写进去。如果用命令行导入报错先确认 sql 文件开头有没有 CREATE DATABASE 语句——如果脚本里没有建库语句就得先手动建一个同名数据库再导入。初始化完成后验证一下账号数据SELECT sno, password FROM student WHERE sno stu; SELECT tno, password FROM teacher WHERE tno tch;资源自带的初始账号是管理员 admin/123、教师 tch/123、学生 stu/123。注意 admin 账号一般不在 student 或 teacher 表里要么脚本单独建了 admin 表要么登录代码里对 admin 做了硬编码判断。导入脚本后先跑这两条查询能确认业务表里有没有数据避免后面登录时查不到记录。3.3 JdbcConfig 数据库连接配置改密码要求和时区参数数据库账号密码配置在 src/com/service/JdbcConfig 这个类里。资源里的默认值是用户名 root、密码 123456如果你的 MySQL root 密码不是这个不改这里直接启动必然报 Access denied。打开 JdbcConfig核心代码是这个结构package com.service; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class JdbcConfig { private static final String URL jdbc:mysql://localhost:3306/student_course ?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; public static Connection getConnection() throws SQLException { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new SQLException(MySQL 驱动未找到请确认 lib 下的 jar 已加入项目, e); } return DriverManager.getConnection(URL, USER, PASSWORD); } }这里最需要注意的是 URL 里的三个参数。useSSLfalse 是 MySQL 8 连接时最常见的坑不关掉 SSL 会报 SSL 相关异常serverTimezoneAsia/Shanghai 指定时区因为 MySQL 8 的驱动要求明确时区否则报 CST 时区错误characterEncodingutf8 解决中文乱码。password 字段改成你自己 MySQL 的 root 密码即可。如果你本地数据库名不叫 student_courseURL 末尾的库名也要一并改掉。提示改完 JdbcConfig 后一定要在 IDEA 里确认 lib 目录下的 mysql-connector-j-8.3.0.jar 已经被加入项目依赖否则编译不报错运行时一执行数据库操作就抛 ClassNotFoundException。4. 核心功能拆解登录鉴权、选课防重复与成绩管理4.1 登录界面的角色校验与跳转逻辑登录是这套系统的门面也是最容易暴露设计缺陷的地方。资源里三个角色共用同一个登录界面输入账号密码后点击登录按钮触发监听器里的校验逻辑。常见实现是把登录方法写到 service 层界面层只负责拿输入框的值和弹出结果提示。public String doLogin(String username, String password) { if (admin.equals(username) 123.equals(password)) { return 管理员; } String teacherSql SELECT tno FROM teacher WHERE tno ? AND password ?; try (Connection conn JdbcConfig.getConnection(); PreparedStatement ps conn.prepareStatement(teacherSql)) { ps.setString(1, username); ps.setString(2, password); ResultSet rs ps.executeQuery(); if (rs.next()) { return 教师; } } catch (SQLException e) { e.printStackTrace(); } String studentSql SELECT sno FROM student WHERE sno ? AND password ?; try (Connection conn JdbcConfig.getConnection(); PreparedStatement ps conn.prepareStatement(studentSql)) { ps.setString(1, username); ps.setString(2, password); ResultSet rs ps.executeQuery(); if (rs.next()) { return 学生; } } catch (SQLException e) { e.printStackTrace(); } return 登录失败; }这段逻辑里有两个值得注意的点。第一是管理员直接硬编码判断虽然简单但可维护性差想改成从数据库读就要再加一张 admin 表第二是教师和学生分开查两张表每个连接都新建一个 Connection如果后续要优化可以把两次校验合并成一次查询加 role 字段。PreparedStatement 的 ? 占位符是必须保留的千万不能用字符串拼接 SQL那是典型的注入漏洞。返回角色字符串后界面层据此决定打开哪个窗口同时把当前用户信息传过去供后续操作使用。4.2 学生选课防止重复选课与冲突检测选课功能是业务逻辑的重头戏也是比较容易做出 bug 的地方。学生选课界面的核心动作是选择一门课程点击选课按钮先检查是否已经选过再插入选课记录。很多初学者直接写一条 INSERT 语句结果学生重复点击就把同一条选课记录插进去两次。public boolean selectCourse(int studentId, int courseId) { String checkSql SELECT COUNT(*) FROM student_course WHERE student_id ? AND course_id ?; String insertSql INSERT INTO student_course(student_id, course_id, selected_time) VALUES(?, ?, NOW()); try (Connection conn JdbcConfig.getConnection()) { conn.setAutoCommit(false); try (PreparedStatement checkPs conn.prepareStatement(checkSql)) { checkPs.setInt(1, studentId); checkPs.setInt(2, courseId); ResultSet rs checkPs.executeQuery(); if (rs.next() rs.getInt(1) 0) { return false; } } try (PreparedStatement insertPs conn.prepareStatement(insertSql)) { insertPs.setInt(1, studentId); insertPs.setInt(2, courseId); insertPs.executeUpdate(); } conn.commit(); return true; } catch (SQLException e) { e.printStackTrace(); return false; } }这里的关键是 setAutoCommit(false) 和 commit() 配合把「检查是否已选」和「插入选课记录」放进同一个事务。如果不放在事务里两个操作之间如果有其他请求插入仍可能产生重复选课。选课表里最好再给 student_id 和 course_id 加唯一索引双保险。返回 false 后界面层弹出提示框说「该课程已选过」而不是让用户看到奇怪的数据库异常。4.3 教师成绩录入与学生查询JTable 刷新与边界值处理成绩管理模块涉及两个方向的操作教师录入和修改成绩学生查询成绩。教师界面一般用 JTable 展示选课列表点击某行后填写分数学生界面则是输入学号查成绩单。录入成绩时要校验分数范围0 到 100 之外的值直接拒绝。public ListScoreVO queryScore(int studentId) { String sql SELECT c.cno, c.name, sc.score, c.credit FROM score sc JOIN course c ON sc.course_id c.id WHERE sc.student_id ?; ListScoreVO list new ArrayList(); try (Connection conn JdbcConfig.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, studentId); ResultSet rs ps.executeQuery(); while (rs.next()) { ScoreVO vo new ScoreVO(); vo.setCourseNo(rs.getString(cno)); vo.setCourseName(rs.getString(name)); vo.setScore(rs.getInt(score)); vo.setCredit(rs.getInt(credit)); list.add(vo); } } catch (SQLException e) { e.printStackTrace(); } return list; }查询成绩时用 JOIN 把选课表、课程表和成绩表关联起来这样界面上能直接展示课程编号、课程名、学分和分数不用前端再拼接。教师录入成绩后的 JTable 刷新是一个容易忽略的细节插入或更新数据后要重新执行 queryScore 并调用 tableModel.setDataVector 刷新表格否则界面还显示旧数据容易被认为录入失败。分数校验在 SQL 层可以加 CHECK 约束在界面层也要判断双重保险。5. 避坑指南Swing 项目从导入到跑通的五个常见问题5.1 运行时报 ClassNotFoundException: com.mysql.cj.jdbc.Driver现象项目编译通过但一点登录按钮或执行查询就抛 java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因lib 目录下的 mysql-connector-j-8.3.0.jar 没有被 IDEA 加入项目依赖。IDEA 的编译过程里文件在项目目录下不代表 JVM 运行时能加载。解决打开 File - Project Structure - Libraries点击加号把 lib 目录下的 jar 添加进去确认勾选 module 后重新运行。这个错误在课程设计答辩演示时出现频率极高很多人打包给别人复现时也会漏掉这个步骤。5.2 MySQL 8 连接报 SSL 错误或 Public Key Retrieval is not allowed现象启动系统后控制台出现 SSL 连接相关报错或提示 Public Key Retrieval is not allowed for user。原因MySQL 8 默认认证插件是 caching_sha2_password且 JDBC 驱动默认开启 SSL。本地测试环境没有配置证书驱动想从服务器取公钥又被安全策略拦住了。解决在 JdbcConfig 的连接 URL 上追加 useSSLfalse 和 allowPublicKeyRetrievaltrue 两个参数。前者关闭 SSL 检查后者允许客户端从服务端获取公钥。这是 MySQL 8.0 与 mysql-connector-j 8.x 组合下最常见的玄学报错按参数照抄即可。5.3 界面和数据库里中文全是问号现象登录界面按钮文字正常但数据库里保存的学生姓名显示为 ??或者从数据库查出来的中文名称在界面显示乱码。原因多层编码不一致。数据库表字符集不是 utf8、连接 URL 没指定 characterEncoding、IDEA 控制台编码不是 UTF-8这三处只要有一处不对中文就会翻车。解决先确认连接 URL 带 characterEncodingutf8再看 MySQL 表结构SHOW CREATE TABLE student 确认 DEFAULT CHARSETutf8最后把 IDEA 的 File Encoding 设为 UTF-8数据库连接在 Navicat 里也对应设为 UTF-8。顺序不要反先查连接参数再查表结构。5.4 点击按钮后界面卡死现象点击查询按钮后窗口直接无响应鼠标转圈过几秒甚至几十秒才恢复数据库操作这段时间里窗口完全不能拖拽。原因数据库查询写在了 Swing 的事件分发线程 EDT 里。Swing 是单线程模型所有界面绘制和事件处理都在 EDT 上如果在这条线程里执行耗时查询界面重绘就被阻塞。解决把数据库查询放到 SwingWorker 或普通子线程里执行查询完成后通过 SwingUtilities.invokeLater 回填结果。这是 Swing 项目必踩的一个坑课程设计里数据量小可能不明显但只要是真实环境一卡一个准。正确的分工是事件监听器只负责启动查询线程界面的更新必须回到 EDT。5.5 Navicat 导入 SQL 脚本失败现象用 Navicat 运行项目里的 sql 文件时卡住、报语法错误或者提示数据库不存在。原因三件事容易忽视。一是脚本开头没有 CREATE DATABASE目标库还没建二是脚本里可能包含函数或触发器Navicat 直接双击运行和命令行运行的处理方式不完全一致三是 sql 文件编码和 Navicat 默认编码不一致导致中文乱码导致语法判断失败。解决先手动创建一个与项目名一致的数据库再右键数据库选择「运行 SQL 文件」文件编码选 UTF-8。不要直接在「查询」窗口里复制整个脚本执行碰到存储过程或函数会出各种边界问题。导入成功后核对一下表数量和数据行数别直接关掉。6. 把项目打包成可执行 Jar验证与交付的最后一公里6.1 IDEA Artifacts 打包步骤课程设计交付时老师大概率会要一个能直接运行的东西总不能在答辩现场让老师自己开 IDEA 跑源码。把系统打包成可执行 Jar 是必要的收尾动作。IDEA 里选择 File - Project Structure - Artifacts新增 JAR - From modules with dependencies主类选登录窗口类确认 lib 目录下的驱动 jar 会被打进包或拷贝到输出目录。java -jar StuSystem.jar注意如果打包时 Manifest 没写主类双击 jar 没反应控制台运行会提示 no main manifest attribute。解决方法是告诉 IDEA 哪个类带 main 方法重新构建。如果数据库驱动没有打进去还需要把 lib 下的 mysql-connector-j-8.3.0.jar 放在 jar 同级目录用下面这种方式指定依赖路径java -cp StuSystem.jar:lib/mysql-connector-j-8.3.0.jar com.view.LoginFrame6.2 一条验证路径确认系统闭环打包前我习惯用一条完整路径验证系统没跑偏启动程序 - admin/123 登录 - 新增一个学生账号 - 退出后用学生账号登录 - 选一门课 - 用 tch/123 登录 - 给该学生录成绩 - 再用学生账号登录查询成绩。这条路径覆盖了三个角色、两张业务表和登录鉴权走通了才算交付完成。角色操作预期结果管理员 admin/123新增学生列表出现新学生学生 stu/123选课选课表新增一条记录且重复选被拦截教师 tch/123录成绩分数写入超范围分数被拒绝学生 stu/123查成绩能看到课程名和分数这套系统非常适合拿来做课程设计答辩因为每个模块都能对应到具体的 Java 基础知识点登录对应 JDBC 和 PreparedStatement选课对应事务成绩对应 JOIN 查询。从那以后我每次拆 Swing 课程设计都强制走一遍「导库 → 改 JdbcConfig → 验证三条角色路径 → 打包 Jar」四步流程任何一步卡住就回到对应的检查点查参数和依赖这套思路帮你省下大量现场排错的时间。希望帮到你。本文还有配套的精品资源点击获取