基于Java Swing和MySQL的学生选课管理系统全解析

发布时间:2026/10/18 9:47:32

基于Java Swing和MySQL的学生选课管理系统全解析 简介一套基于Java Swing与MySQL的学生选课管理系统项目适配IntelliJ IDEA面向Java初学者及需要完成课程设计、毕业设计的学生。系统划分为系统管理、数据管理和数据查询三大部分系统管理实现密码设置、用户登录和退出数据管理支持学生、课程、选课三个模块的增加、删除、修改操作数据查询可分别检索学生、课程及选课信息功能覆盖完整层次分明适合作为Java图形界面开发与MySQL数据库应用的参考模板也方便在此基础上扩展业务逻辑。资源包共3个文件压缩后大小3.34MB其中zip为可运行的项目源码sql为数据库初始化脚本docx为实训报告文档拿到手即可对照使用。运行环境要求JDK8和MySQL5.7以上兼容IDEA/Eclipse能够帮助读者逐步理解Swing界面构建、JDBC连接以及增删改查等关键实现。已有268人学习下载对于需要快速搭建课设项目或借鉴选课系统业务流程的开发者是一份实用的操作素材。1. 学生选课管理系统为什么我推荐用 Java Swing 而不是 Web 技术栈做课程设计或者毕设的时候很多同学第一反应是选课系统肯定要用 Web 做用 JSP、Spring Boot 加个前端页面——但如果你只是想交付一份能运行、能讲清楚、能通过答辩的完整方案Java Swing 加 MySQL 反而是更稳的选择。这套基于 IDEA 环境的学生选课管理系统把系统管理、数据管理、数据查询三条主线全部落地代码量适中逻辑清晰还附带实训报告和数据库脚本属于典型的开箱即改型项目。适合正在做 Java 课程设计、需要一份完整可运行代码加文档的同学也适合想快速搭一个桌面端管理系统练手 Swing 事件监听和 JDBC 操作的开发者。接下来我会按需求拆解 → 总体设计 → 模块实现 → 常见坑 → 验收答辩这条完整链路把这个方案讲透让你拿到手之后不只是会跑还能讲清楚每一处设计为什么这么做。2. 需求分析与功能拆解三大模块到底在管什么2.1 从用户故事看系统边界这套系统面对的角色很清晰管理员教务人员是唯一操作者。系统不做多角色权限分化而是把精力集中在数据维护和数据查询两件核心事上。我一般拿到这种需求先不急着写代码而是把用户故事列出来管理员要能登录系统并且修改自己的密码管理员要能维护学生档案包括新增、删除、修改学生信息管理员要能维护课程库课程的增加、删除、修改随时可做最关键的是选课关系管理学生和课程的多对多关系要通过一张选课表解耦不能直接往学生表里塞课程字段。从这些故事可以倒推系统必须有三张核心表——学生表、课程表、选课表。用户信息单独一张表存管理员账号密码。密码设置功能不是改别人的密码而是改当前登录管理员的密码这点在实现时容易做歪很多新手会把密码管理做成用户管理其实这里只需要对当前会话用户生效即可。退出功能更简单清掉当前登录状态回到登录窗口。整个系统没有注册入口所有账号由数据库预置这符合课设场景的封闭性。2.2 数据管理模块的功能粒度划分数据管理是工作量最大的部分也被拆成了三块学生管理、课程管理、选课管理。每块下面都有三个动作添加、删除、修改。这里有一个设计决策值得注意学生管理和课程管理的增删改直接操作对应表但选课管理的增删改本质上是在维护选课关系表。添加选课记录时学生 ID 和课程 ID 必须是下拉选择而不是手输因为手输容易出现外键不存在的脏数据。删除选课记录时直接按选课 ID 删一行即可。修改选课时通常的做法是先删除再重新添加或者把学生 ID、课程 ID 两个外键字段做成可更新的下拉框。但这里有个常见设计陷阱课程管理里如果删除一门已经有学生选的课程数据库会因为外键约束报错。所以代码里必须先做该课程是否被引用的检查引用数大于 0 就提示课程已存在选课记录禁止删除。同样删除学生前也要检查该学生是否有选课记录。这个细节不做答辩时老师随便一测就会翻车。2.3 数据查询模块按维度下钻而不是做一张大表查询模块也分三个入口查询学生信息、查询课程信息、查询选课信息。最简单的做法是每个查询窗口放一个 JTable把所有数据塞进去。但更好的方案是带条件查询学生信息按学号或姓名模糊匹配课程信息按课程名模糊匹配选课信息按学生 ID 关联查询出学生姓名加课程名称的组合结果。这三条查询分别对应三条 SQL选课查询必须用 JOIN 把学生姓名和课程名称带出来否则只显示两个 ID老师会认为你没有理解关系型数据库的核心价值。从需求到实现的映射关系很明确系统管理对应登录验证和会话控制数据管理对应增删改事务数据查询对应 JOIN 查询和模糊匹配。功能点不多但覆盖了 Java 课设几乎所有的必考知识点——GUI 事件处理、JDBC 预编译、ResultSet 遍历、外键约束处理、聚合查询。这套结构如果讲不清后面代码写得再花哨也白搭。3. 总体架构设计与数据库建模三张核心表加一张用户表的拆分逻辑3.1 分层结构界面、业务、数据三层怎么划分整个项目不是把 SQL 写在按钮事件里就完事而是按三层思路组织。界面层是各个 JFrame 窗口负责收集输入、展示结果、触发事件业务层处理逻辑判断比如删除前检查引用、登录时比对密码、修改时校验必填项数据层用 JDBC 封装增删改查方法统一管理 Connection、PreparedStatement、ResultSet 的关闭。项目里没有强行引入 Dao 接口和 Service 接口的抽象层而是用类名区分职责比如 StudentDao、CourseDao、SelectCourseDao 各管各的表这在课设体量下是最务实的做法。这样做的好处是答辩时能说清楚高内聚低耦合。比如把数据库连接参数抽到配置里换数据库只需要改 URL把每个表的增删改查单独放一个类查询窗口要复用添加窗口的学生列表时直接调用 StudentDao.getAllStudents() 即可。如果学号文本框和删除按钮的事件里各写一遍 SQL那代码维护性就是负数老师看到会追问重构思路。3.2 数据库设计字段、类型、约束一次到位数据库脚本由 studb.sql 提供核心是四张表。学生表字段包括学号主键、姓名、性别、年龄、班级、入学年份等课程表字段包括课程号主键、课程名、学时、学分、任课教师选课表是关系表包含选课记录 ID 主键、学生学号外键、课程号外键并加 UNIQUE 约束防止同一个人重复选同一门课用户表保存管理员账号和密码密码字段建议存储加密后的值但课设项目里通常直接明文存储只要能跑通即可答辩时可以主动提一句生产环境必须加盐加密来展示你的安全意识。选课表的联合唯一索引是这个设计的点睛之笔。如果不在数据库层面加约束代码里要判断这个学生是否已经选了这门课只能先查一遍再插入存在并发窗口期。加了 UNIQUE(学号, 课程号) 之后重复插入直接抛异常代码里捕获 DuplicateKeyException 提示该学生已选此课程即可。建议你在设计文档里把这条索引明确写出来它体现了数据库层的防重设计是加分项。3.3 运行环境与版本匹配项目基于 JDK 8 开发数据库要求 MySQL 5.7 以上IDE 用 IDEA。这里有一个隐蔽的坑MySQL 8.0 的 JDBC 驱动和 5.x 的驱动在连接 URL 上不一样。MySQL 5.x 的连接串是 jdbc:mysql://localhost:3306/studb?useSSLfalseMySQL 8.x 需要加 serverTimezoneAsia/Shanghai 或者 useUnicodetruecharacterEncodingutf8否则驱动会报时区错误。项目里如果用的是 mysql-connector-java 5.1.x 的 jar 包连 MySQL 8.0 时会连上但中文乱码连 MySQL 5.7 时建议把 useSSL 关掉避免警告刷屏。后面避坑章节我会细讲这个问题。数据库命名建议统一用 studb表名前缀不加模块名直接 student、course、sc、user。字段命名全小写下划线避免用 name、id 这种过于泛化的名字。建表语句里要写清楚外键约束和索引这样导入 studb.sql 后有据可查。4. 模块实现与关键代码登录、增删改查、查询联动的落地写法4.1 登录窗口与会话状态控制登录窗口的逻辑集中在验证账号密码这一个动作上。点击登录按钮后从文本框取出用户名和密码调用 UserDao 的 login 方法返回布尔值。成功后把当前用户信息保存在一个全局静态变量里主窗口通过这个变量判断是否已登录未登录直接关闭主窗口退出系统。密码修改功能读取当前用户先验证旧密码再更新为新密码。public boolean login(String username, String password) { String sql SELECT id FROM user WHERE username ? AND password ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); ResultSet rs ps.executeQuery(); return rs.next(); // 只要有一条记录就说明账号密码匹配 } catch (SQLException e) { e.printStackTrace(); return false; } }这段代码用了 PreparedStatement 的占位符而不是拼接字符串可以防止 SQL 注入。这是课设答辩的高频考点——老师会问为什么不直接用 Statement你要能回答出参数化查询的两个好处防注入、免去手动处理单引号转义。登录成功后主窗体的 JMenuBar 按功能分组系统管理菜单放密码设置和退出数据管理菜单放学生、课程、选课三个入口查询菜单放三个查询窗口。菜单的 enable 状态在登录前全部置灰登录后才放开这个小细节能体现会话控制意识。4.2 学生管理的增删改窗口复用和校验逻辑学生管理的主界面是一个 JTable 加三个按钮。选表格哪一行点击修改按钮时弹出一个带学生信息的编辑窗口窗口内文本框预填当前行的值。添加和修改共用一个窗口类通过构造参数传入是添加还是修改的标记以及被修改行的主键值减少重复代码。private void saveStudent() { String idText txtId.getText().trim(); String nameText txtName.getText().trim(); if (idText.isEmpty() || nameText.isEmpty()) { JOptionPane.showMessageDialog(this, 学号和姓名不能为空); return; } Student stu new Student(idText, nameText, txtGender.getText().trim(), Integer.parseInt(txtAge.getText().trim()), txtClass.getText().trim()); if (isEditMode) { studentDao.updateStudent(stu); // 修改模式按主键更新 } else { studentDao.insertStudent(stu); // 添加模式执行插入 } refreshTableData(); // 刷新主表格 dispose(); // 关闭当前编辑窗口 }校验逻辑要前置不要等数据库抛异常再弹错误。学号为空、姓名为空这些必填项在按钮事件里先拦下来。年龄字段严格来说是数值类型但 JTextField 拿到的永远是字符串转 int 时如果用户输入非数字会抛 NumberFormatException所以要么用 JSpinner要么加 try-catch 给友好提示。我这边的做法是换行 Int 解析结果存进 int 变量时用 try-catch失败则提示年龄必须为数字。删除按钮的逻辑要分两步走。先查该学生是否存在于选课表存在就提示先删除选课记录不存在才执行 DELETE FROM student WHERE id ?。这个检查建议在业务层做而不是用数据库级联删除。因为课设场景下老师希望看到你自己处理关联数据的逻辑直接 ON DELETE CASCADE 虽然省事但掩盖了业务规则。4.3 选课管理的核心外键下拉框和防重复选课选课管理是整个系统里最容易写乱的部分。添加选课时学生 ID 和课程 ID 不能用文本框必须用两个 JComboBox数据分别来自 StudentDao.getAllStudents() 和 CourseDao.getAllCourses()。下拉框里显示学号 姓名或者课程号 课程名但存储时只取对应 ID。public void addSelectCourse(String stuId, String courseId) { String sql INSERT INTO sc(stu_id, course_id, select_time) VALUES(?, ?, NOW()); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, stuId); ps.setString(2, courseId); ps.executeUpdate(); } catch (SQLIntegrityConstraintViolationException e) { // 学号或课程号不存在或者选课关系重复 JOptionPane.showMessageDialog(null, 该学生已选此课程或学生/课程不存在); } catch (SQLException e) { e.printStackTrace(); } }这里的核心思路是数据库已有的 UNIQUE 约束是最后一道防线代码里不要先 SELECT 再 INSERT。直接尝试插入唯一索引冲突时捕获特定异常提示即可。SQLIntegrityConstraintViolationException 是 JDBC 抛出的约束违反异常MySQL 的重复键错误也会归到这里用这个捕获比 catch(Exception) 更精准。选课时间字段用数据库的 NOW() 函数填充而不是在 Java 里 new Date()这样时间以数据库服务器为准避免本机时间不准的问题。4.4 三条查询链路的 SQL 写法查询学生信息和课程信息比较简单单表查询加模糊条件。选课查询必须 JOIN 两张表才能显示名字而不是 ID。建议把选课查询做成可以看到完整信息的视图选课记录号、学号、学生姓名、课程号、课程名、学分、选课时间。SQL 大概是 SELECT sc.id, s.id, s.name, c.id, c.name, c.credit, sc.select_time FROM sc JOIN student s ON sc.stu_id s.id JOIN course c ON sc.course_id c.id。条件查询时在 WHERE 后面加 s.name LIKE ? 参数参数值传 %关键字% 即可。三个查询窗口建议共用同一个刷新方法查询按钮触发时按条件查询点击显示全部按钮时清空条件重新查。查询结果放到 JTable 时要把 ResultSet 的数据先存进 DefaultTableModel设置好列名数组再把 JTable.setModel 换掉。每次查询前先清空旧 model避免点击多次按钮后数据叠加。private void refreshTable(String conditionSql, Object... params) { DefaultTableModel model new DefaultTableModel(); model.setColumnIdentifiers(new String[]{选课记录号, 学号, 姓名, 课程号, 课程名, 学分, 选课时间}); ListObject[] rows selectCourseDao.queryWithCondition(conditionSql, params); for (Object[] row : rows) { model.addRow(row); } table.setModel(model); }5. 避坑指南与常见问题排查运行期最容易翻车的五个点5.1 现象IDEA 运行后报 java.sql.SQLException: The server time zone value原因MySQL 8.x 驱动要求连接 URL 必须指定时区项目里如果用的是 JDK 8 自带的时间区或默认时区会直接抛异常。解决在 JDBC URL 后面加 serverTimezoneAsia/Shanghai 以及 useSSLfalse。如果你的 mysql-connector-java 是 8.0 以上版本还需要确认 mysql-connector-java 和 MySQL 服务器版本兼容。通常的做法是统一用 mysql-connector-java 8.0.28它可以连 MySQL 5.7 和 8.0。5.2 现象中文乱码学生姓名显示为问号原因数据库连接 URL 没指定字符集或者建库时字符集不是 utf8mb4。解决建库语句用 CREATE DATABASE studb DEFAULT CHARACTER SET utf8mb4连接 URL 加 useUnicodetruecharacterEncodingutf8。如果已经导入 studb.sql 但乱码用命令 ALTER DATABASE studb CHARACTER SET utf8mb4 再重跑程序。IDEA 方面检查 Run Configuration 的 VM options 是否需要加 -Dfile.encodingUTF-8大多数情况不需要但如果 JVM 默认编码是 GBK就加一下。5.3 现象删除学生时报外键约束错误但代码里明明没有级联原因选课表 sc 里还残留着该学生的选课记录。解决删除学生前先执行删除选课记录的 SQL或者按我前面说的先查询 sc 表有没有引用有就拦截提示。更稳妥的方式是把删除操作包在一个事务里先 DELETE FROM sc WHERE stu_id ?再 DELETE FROM student WHERE id ?两个都成功才提交。这样可以避免选课记录删了但学生没删掉的中间状态。5.4 现象修改学生信息时主键学号被改动导致关联数据断裂原因学生表的学号是主键如果修改窗口允许编辑学号更新后 sc 表里的 stu_id 还指向旧学号数据就乱了。解决修改模式下学号文本框设置为不可编辑setEditable(false)只允许改姓名、班级、年龄等非主键字段。如果非要支持改学号必须同步更新 sc 表里的 stu_id但课设里不建议做这个容易引出一些列级联更新问题。我一般会在编辑窗口的初始化方法里做判断——isEditMode 为 true 时把主键输入框 setEnabled(false)。5.5 现象登录成功后主窗口可以打开多个点击按钮也没反应原因登录窗口没有 dispose主窗口 new 了多次多个窗口互相覆盖或者线程没处理 Swing 事件队列按钮监听器里执行了耗时 SQL 导致界面卡死。解决登录成功执行 dispose 关闭登录窗口主窗口只 new 一次。查询和刷新操作如果确实慢用 SwingWorker 放到后台线程执行防止 UI 冻结。不过课设数据量很小通常不需要多线程但要养成习惯不要在 EDT事件派发线程里做长耗时操作。排查方法是看控制台有没有异常堆栈很多同学报没反应其实是 SQL 报错但弹窗代码被吞了。6. 验收清单与答辩准备怎么证明这套系统是完整的6.1 按功能点逐项验收把测试记录写进实训报告你拿到项目后不要急着打开就跑先按功能清单逐项验证。我建议做一个验收表格登录模块验证正确密码能进、错误密码有提示、密码修改后旧密码失效学生管理验证添加成功后表格刷新、学号重复时有报错提示、删除被选课的学生被拦截课程管理验证课程学分字段只能输数字、删除被引用课程被拦截选课管理验证同一学生重复选同一课程被拦截、下拉框数据来自数据库而非写死查询模块验证模糊查询能命中、选课查询结果带学生姓名和课程名。每过一条打一个勾把测试结果截图放进实训报告这就是最强的答辩材料。6.2 答辩时必被追问的五个技术点提前准备答案第一个问题PreparedStatement 和 Statement 的区别。标准答案是预编译、防 SQL 注入、处理特殊字符更方便。第二个问题Swing 的事件监听机制你要能说出 ActionListener 和 ItemListener 分别在什么场景用——按钮点击用前者下拉框切换用后者。第三个问题数据库表关系你要画出 student、course、sc 的多对多关系图并解释为什么需要中间表。第四个问题为什么选择 Swing 而不是 JavaFX 或 Web可以从课设复杂度、桌面管理系统的适用性、Swing 与 JDBC 结合简单三个角度回答。第五个问题项目里哪里体现了面向对象思想——Dao 类封装数据库操作、Student/Course 实体类对应表结构、StudentManagerFrame 组合了 TableModel 和 StudentDao。6.3 最后一轮自查从代码规范到文档完整性代码层面检查是否每个类都有注释说明职责、是否有 System.out.println 残留调试输出有就删掉或改成日志、连接资源是否在 finally 或 try-with-resources 中关闭。数据库层面检查 studb.sql 能否在干净的 MySQL 实例上重复导入不报错建议你在另一台电脑上重新导入测试一遍避免存在环境依赖。文档层面检查实训报告是否包含项目概述、需求分析、数据库设计、核心代码说明、测试截图、总结展望。完整资源里自带课程设计报告文档你只需要把运行截图和个人信息替换进去即可。从我的经验来看答辩最大的风险不是代码写不出来而是讲不清楚设计决策。比如选课记录为什么用单独的表为什么删除要做引用检查数据库连接串为什么那么长每一个点都是展示你理解深度的机会。我后来每次做类似项目都强制自己走一遍验收清单流程——先把数据库导入干净库再把每个功能点操作一遍并截图最后把异常场景密码错误、重复选课、删除被引用数据也测一遍写进报告。这样最终交付的不只是一段能跑的代码而是一套能说服人的完整方案。希望这套思路能帮到你让课设从能运行变成能讲透。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/18 9:47:32

青少年开源参与指南:从零开始第一次PR到开源社区成长路径

1. 先从背景说起:为什么会有“青少年开源”这个议题1.1 社区里那些让我意外的年轻人这几年混迹各种开源社区和线下技术活动,有个现象越来越明显:出现在贡献者列表里的年轻面孔越来越多了。以前遇到一个高中生PR(Pull Request&…

2026/10/18 9:42:32

一帧画面八道关:rebucca视频行为分析平台源码拆解

最近在做工业场景的 AI 监控方案选型时,我注意到一个很有意思的开源项目:rebucca 视频行为分析平台。它主打工业环境下的实时行为识别,而且最吸引人的一点是“一行命令就能跑起来”,不需要折腾一堆依赖。真正开始读源码之后&#…

2026/10/18 9:42:32

Markdown流式渲染:构建AI生成式UI的结构信标

1. 项目概述:这不是一次简单的格式转换,而是一场交互范式的迁移“从 Markdown 到生成式 UI:AI 应用中的流式渲染实践”——这个标题里藏着三个关键动作:“从…到…”是路径,“生成式 UI”是目标形态,“流式…

2026/10/18 14:48:19

Whisper离线部署实战:编译whisper.cpp与量化模型优化指南

简介:一套基于whisper.cpp深度定制的离线语音识别完整工程,面向需要在本地或内网环境部署语音转写能力的开发者、嵌入式及桌面应用工程师。资源包将C推理引擎与Go服务端无缝衔接,通过CGO调用封装,配合预编译的tiny、base、small三…

2026/10/18 14:48:19

提示词工程终局:文件系统思维让Agent真正可扩展

先说一个现象:开源项目能到 20 万星,本身就是一件非常离谱的事。而如果这个项目还是零营销、零融资、纯靠社区口碑滚出来的,那基本可以断定,它踩中的绝对不是某个小圈子的自嗨需求,而是一个普遍存在的、大家一直在忍的…

2026/10/18 14:48:19

2026开题季文献综述实战:AI工具链如何高效梳理领域脉络

每年到开题季,实验室群里聊得最热闹的话题永远是文献综述。尤其对2026届研究生而言,开题报告里最难啃的骨头基本都集中在文献综述:要证明你读过足够多的东西、能理清领域脉络、还得找到别人没做过的缝隙下手。很多同学一到这个阶段就开始焦虑…

2026/10/18 14:48:19

FastAPI入门到实战:五个Demo从零搭建接口并接入DeepSeek大模型

1. 从一条路由接到 DeepSeek:为什么我只写五个 Demo如果你和我一样,第一次打开 FastAPI 的官方文档时,被里面异步、Pydantic、依赖注入、WebSocket 这些概念砸得有点懵,那么这篇文章就是写给你的。我的入门路线很简单:…

2026/10/18 14:43:18

基于YOLOv8的商场客流统计系统实战:数据集、跟踪与部署全解析

商场做客流统计这件事,听起来简单,真做起来坑不少。早几年用红外对射或者WiFi探针的方案,精度和抗干扰能力都一言难尽。现在基于深度学习的目标检测技术成熟了,用YOLO系列去做视觉客流统计成了主流方案,精度高、部署灵…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑