news 2026/10/26 7:44:34

Java Swing选课系统:纯JDBC+MySQL课设最小可行体

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java Swing选课系统:纯JDBC+MySQL课设最小可行体

简介:这是一份面向Java初学者与高校计算机专业学生的课程设计级项目资源,完整实现了基于Swing GUI与MySQL数据库的学生选课管理系统,覆盖登录、课程管理、学生选课、已选课程查看、密码修改等核心业务流程,功能完备且代码结构清晰,适合作为Java GUI开发与数据库交互的实践范例。资源包共165个文件,含23个Java源码文件、63个编译后Class类、24个JForm设计器生成的GUI界面文件,以及SQL建库脚本、Navicat导入数据说明、系统运行演示AVI视频、配套文档与图片素材,整体大小58.82MB,便于快速导入Eclipse并调试运行。已有550人学习下载,资源附带可直接播放的操作录屏视频,直观展示系统全流程交互;所有界面类(如MainFrm_admin、SelectCourseInterFrm、StudentViewInterFrm等)命名规范、职责明确,利于理解MVC雏形结构;SQL脚本与数据库配置说明齐全,显著降低环境搭建门槛。

1. 这不是“又一个Java课设”,而是能跑通、能改、能交、能答辩的选课系统最小可行体

你手头这个.zip文件,名字里带“95分以上课设”,但真正值钱的不是分数——是它没用Spring Boot、没套MyBatis Plus、没堆前端框架,就靠纯Swing + JDBC + MySQL原生组合,把学生、课程、教师、选课四张表跑通了事务、校验、界面跳转和数据一致性。我去年帮三个学院改过这类课设,翻车最多的是:界面卡死在登录后空白、选课成功但数据库没写入、退课时删错行、导出Excel乱码、MySQL 8.0连不上报Public Key Retrieval is not allowed……而这个源码包,恰恰避开了这五类高频翻车点。它不炫技,但每处代码都带着“答辩老师现场敲命令验证”的预设——比如登录用PreparedStatement防SQL注入,选课前查学分上限用SELECT SUM(credit)而非内存累加,退课触发ON DELETE CASCADE级联删除。适合两类人:大二刚学完JDBC想交作业的,或需要快速搭个管理后台原型的工程师(别笑,真有小公司拿它改两页当内部教务MVP)。

提示:这不是Web系统,不涉及Tomcat、Servlet、HTTP协议;也不是JavaFX项目,所有UI组件都是JFrame+JTable+JComboBox原生控件;数据库脚本直接建库建表,不依赖Flyway/Liquibase等迁移工具。


2. 从解压到运行:三步验证环境是否就绪,拒绝“运行失败就放弃”

2.1 检查Java与MySQL版本兼容性(血泪经验:JDK 8u291+ 是底线)

这个项目基于Java 8编译(.class文件魔数为CA FE BA BE),但JDK 11+默认禁用javax.swing部分反射调用,会导致JTable渲染异常或JDialog模态失效。必须确认:

java -version # 输出必须含 "1.8.0_" 或 "8u" 字样,如:java version "1.8.0_361" # 若是 JDK 17,需加启动参数:-Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd

MySQL方面,项目SQL脚本使用utf8mb4字符集,MySQL 5.7.8+ 或 8.0.x 均可,但必须关闭严格模式(否则INSERT INTO student VALUES (...)缺字段会报错):

-- 登录MySQL后执行 SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES','')); SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'STRICT_ALL_TABLES',''));

注意:不要用MySQL Installer GUI一路下一步——它默认开启严格模式。务必手动执行上述SQL,或修改my.ini中sql_mode项删掉STRICT_TRANS_TABLES。

2.2 解压后直取关键文件,跳过“找入口类”的玄学时刻

ZIP解压后目录结构极简:

src/ # Java源码(含com.xxxx包) lib/ # mysql-connector-java-5.1.47.jar(重点!不是8.x驱动) sql/ # create_table.sql(建库建表脚本) resources/ # db.properties(数据库连接配置) out/ # 编译后的.class文件(可直接运行)

入口类是com.system.MainFrame(不是Main.java或Application.java),这是Swing项目典型设计:MainFrame继承JFrame,main()方法在其中。编译命令必须指定lib下驱动:

# Windows下进入src目录执行 javac -cp ".;../lib/mysql-connector-java-5.1.47.jar" com/system/MainFrame.java # Linux/macOS用冒号分隔 javac -cp ".:../lib/mysql-connector-java-5.1.47.jar" com/system/MainFrame.java

逻辑说明:mysql-connector-java-5.1.47.jar是MySQL 5.x专用驱动,若强行换8.0.28.jar,Class.forName("com.mysql.jdbc.Driver")会抛ClassNotFoundException(因8.x驱动类名变为com.mysql.cj.jdbc.Driver)。项目没改驱动类名,所以必须用5.x驱动。

2.3 数据库初始化:执行SQL脚本前必做的三件事

sql/create_table.sql包含建库、建表、插测试数据,但直接source会失败。必须按顺序操作:

  1. 先创建数据库并指定字符集(否则中文变问号):
    CREATE DATABASE course_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE course_system;
  2. 手动注释掉脚本中DROP TABLE IF EXISTS语句(课设答辩常要求保留历史数据,且首次运行无需删表);
  3. 检查外键约束语法:脚本中student_id外键引用student(id),但MySQL 5.7默认引擎是InnoDB,而CREATE TABLE未显式声明ENGINE=InnoDB,需补全:
    CREATE TABLE selection ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, course_id INT NOT NULL, FOREIGN KEY (student_id) REFERENCES student(id) ON DELETE CASCADE, FOREIGN KEY (course_id) REFERENCES course(id) ON DELETE CASCADE ) ENGINE=InnoDB; -- 必须加这一行!

执行后,用SELECT COUNT(*) FROM student;确认返回3(测试数据含3名学生),即初始化成功。


3. 界面逻辑拆解:为什么登录后能跳转、选课时能实时校验、退课不丢数据

3.1 登录模块:Swing事件链如何避免“点击无响应”黑匣子

登录界面LoginFrame核心是JButton的ActionListener:

loginBtn.addActionListener(e -> { String username = userField.getText().trim(); String password = new String(passField.getPassword()); // 关键!不能用getText() if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(this, "用户名或密码不能为空"); return; } // 数据库校验走独立线程,防GUI冻结 new SwingWorker<Boolean, Void>() { @Override protected Boolean doInBackground() throws Exception { return UserService.login(username, password); // 查user表,返回true/false } @Override protected void done() { try { if (get()) { // get()获取doInBackground返回值 dispose(); // 关闭登录窗 new MainFrame().setVisible(true); // 启动主窗 } else { JOptionPane.showMessageDialog(this, "用户名或密码错误"); } } catch (Exception ex) { JOptionPane.showMessageDialog(this, "系统异常:" + ex.getMessage()); } } }.execute(); });

参数说明:SwingWorker是Swing线程安全核心——doInBackground()在后台线程查库,done()在EDT(事件调度线程)更新UI。若直接在ActionListener里查库,GUI会卡死10秒(尤其网络延迟时),学生常误以为程序崩溃。

3.2 选课功能:三层校验如何堵住“超学分、重复选、课满员”漏洞

主界面MainFrame中选课按钮触发SelectionService.addSelection(),该方法串联三重校验:

  1. 学分上限校验(查student表max_credit字段 +selection表关联course求和):
    SELECT IFNULL(SUM(c.credit), 0) AS used FROM selection s JOIN course c ON s.course_id = c.id WHERE s.student_id = ?;
  2. 课程余量校验(course表capacity减去selection中已选人数):
    SELECT capacity - (SELECT COUNT(*) FROM selection WHERE course_id = ?) AS remain FROM course WHERE id = ?;
  3. 重复选课校验(selection表student_id+course_id联合唯一索引,插入时捕获SQLException):
    ALTER TABLE selection ADD UNIQUE KEY uk_student_course (student_id, course_id);

逻辑说明:这三步必须用单条SQL事务包裹,否则并发选课时可能超限。项目用Connection.setAutoCommit(false)开启事务,任一校验失败则conn.rollback(),成功则conn.commit()。这是课设拿高分的关键细节——答辩老师会故意开两个客户端同时选同一门课测并发。

3.3 数据表格渲染:JTable如何显示中文、居中、自适应列宽

MainFrame中课程列表用JTable展示,但默认列宽挤成一团。关键改造在CourseTableModel:

public class CourseTableModel extends AbstractTableModel { private List<Course> data; // Course实体含id,name,teacher,credit,capacity字段 @Override public Object getValueAt(int rowIndex, int columnIndex) { Course c = data.get(rowIndex); switch (columnIndex) { case 0: return c.getId(); case 1: return c.getName(); // 中文直接return,不编码 case 2: return c.getTeacher(); case 3: return c.getCredit(); case 4: return c.getCapacity(); default: return ""; } } // 列标题本地化(避免英文) @Override public String getColumnName(int column) { String[] names = {"编号", "课程名", "教师", "学分", "容量"}; return names[column]; } }

然后在MainFrame中设置渲染器:

JTable table = new JTable(new CourseTableModel()); // 居中对齐 DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer(); centerRenderer.setHorizontalAlignment(JLabel.CENTER); table.getColumnModel().getColumn(0).setCellRenderer(centerRenderer); // 编号列居中 table.getColumnModel().getColumn(3).setCellRenderer(centerRenderer); // 学分列居中 // 自适应列宽(根据内容最长字符串) table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); for (int i = 0; i < table.getColumnCount(); i++) { TableColumn column = table.getColumnModel().getColumn(i); int width = 80; // 默认宽度 for (int row = 0; row < table.getRowCount(); row++) { Object value = table.getValueAt(row, i); if (value != null && value.toString().length() > width / 8) { width = Math.min(300, value.toString().length() * 12); // 中文字体约12px宽 } } column.setPreferredWidth(width); }

提示:Swing字体渲染依赖系统字体,Windows上若中文乱码,需在MainFrame构造函数开头加:
UIManager.put("Label.font", new Font("微软雅黑", Font.PLAIN, 12));


4. 避坑指南:95分课设背后,那些让答辩老师皱眉的5个致命细节

4.1 现象:登录成功后主界面空白,控制台无报错

原因:MainFrame构造方法中initComponents()调用位置错误。常见误写:

public MainFrame() { setTitle("学生选课系统"); setSize(1000, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); initLayout(); // 错!应在add组件后调用 setVisible(true); // 错!应在所有组件添加完毕后调用 }

解决:必须按Swing生命周期顺序:

  1. 创建组件(JPanel、JTable等);
  2. 设置布局(setLayout(new BorderLayout()));
  3. add()组件到容器;
  4. 最后调用pack()(自动计算尺寸)和setVisible(true)。
    正确写法:
public MainFrame() { initComponents(); // 此方法内完成组件创建、布局、add setTitle("学生选课系统"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); // 关键!否则setSize无效 setLocationRelativeTo(null); // 居中显示 setVisible(true); }

4.2 现象:MySQL 8.0连接报错Could not create connection to database server

原因:驱动版本与MySQL协议不匹配。项目用mysql-connector-java-5.1.47.jar,但MySQL 8.0默认启用caching_sha2_password认证插件,5.x驱动不支持。
解决:

  • 方案A(推荐):降级MySQL用户认证方式(不影响其他应用):
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;
  • 方案B:修改db.properties,在URL末尾加参数:
    jdbc:mysql://localhost:3306/course_system?useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true

    注意:allowPublicKeyRetrieval=true是临时方案,仅用于课设,生产环境需升级驱动。

4.3 现象:选课后数据库selection表有记录,但JTable不刷新

原因:JTable绑定的TableModel未触发fireTableDataChanged()。学生常忘记在SelectionService.addSelection()成功后通知视图:

// 错误:只更新数据库,不通知表格 selectionDao.insert(selection); // 正确:更新模型数据 + 通知刷新 model.addData(selection); // model是CourseTableModel实例 model.fireTableDataChanged(); // 关键!否则界面不变

解决:所有增删改操作后,必须调用TableModel的fireXXX系列方法(fireTableDataChanged()、fireTableRowsInserted()等)。

4.4 现象:导出Excel时中文全是方框(□□□)

原因:Apache POI 3.x默认字体不支持中文,且未设置单元格样式。
解决:在ExportService.exportToExcel()中:

// 创建字体 Font font = workbook.createFont(); font.setFontName("微软雅黑"); // 必须显式设中文字体 font.setFontHeightInPoints((short)10); // 创建样式 CellStyle style = workbook.createCellStyle(); style.setFont(font); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); // 应用到每个单元格 Row row = sheet.createRow(i); for (int j = 0; j < headers.length; j++) { Cell cell = row.createCell(j); cell.setCellValue(data[i][j]); cell.setCellStyle(style); // 关键! }

4.5 现象:打包成JAR后双击无反应,命令行运行报NoClassDefFoundError

原因:未将mysql-connector-java-5.1.47.jar打入CLASSPATH。Swing项目打包需手动合并依赖。
解决:用jar命令合并(Windows):

# 先编译所有.class javac -cp "lib/mysql-connector-java-5.1.47.jar" -d out src/com/system/*.java # 打包时包含驱动 jar -cvfm StudentSystem.jar MANIFEST.MF -C out . lib/mysql-connector-java-5.1.47.jar

其中MANIFEST.MF内容:

Manifest-Version: 1.0 Main-Class: com.system.MainFrame Class-Path: lib/mysql-connector-java-5.1.47.jar

注意:Class-Path路径是JAR内相对路径,若驱动放在lib/目录,则此处写lib/mysql-connector-java-5.1.47.jar;若直接放根目录,则写mysql-connector-java-5.1.47.jar。


5. 从课设到可用:三个真实场景的改造技巧,让代码脱离“作业感”

5.1 场景一:答辩老师要求“增加课程搜索功能”,30分钟内上线

Swing里加搜索框不是简单拖个JTextField。要实现输入即查、模糊匹配、结果高亮,核心是DocumentListener:

searchField.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { doSearch(); } @Override public void removeUpdate(DocumentEvent e) { doSearch(); } @Override public void changedUpdate(DocumentEvent e) { doSearch(); } private void doSearch() { String keyword = searchField.getText().trim(); if (keyword.isEmpty()) { // 恢复全部课程 table.setModel(new CourseTableModel(allCourses)); return; } // 模糊查询SQL(注意SQL注入防护!) String sql = "SELECT * FROM course WHERE name LIKE ? OR teacher LIKE ?"; List<Course> results = query(sql, "%" + keyword + "%", "%" + keyword + "%"); table.setModel(new CourseTableModel(results)); } });

技巧:query()方法用PreparedStatement,?占位符防注入;CourseTableModel需重写getRowCount()和getValueAt()以适配动态数据源。

5.2 场景二:导出报表要按“学院-专业”分组统计选课人数

原始SQL只查单表,需用GROUP BY聚合。在ReportService.generateReport()中:

String sql = """ SELECT s.college AS 学院, s.major AS 专业, c.name AS 课程名, COUNT(*) AS 选课人数 FROM selection sel JOIN student s ON sel.student_id = s.id JOIN course c ON sel.course_id = c.id GROUP BY s.college, s.major, c.name ORDER BY s.college, s.major, 选课人数 DESC """; List<Object[]> reportData = query(sql); // 返回Object[]数组,每行4列 // 用JTable展示时,自定义TableModel处理多级分组

关键在表格渲染:用JTable的setRowHeight()和prepareRenderer()高亮分组首行:

table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c = super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column); // 若当前行学院名与上一行不同,则加粗 if (row > 0 && !value.toString().equals( table.getValueAt(row - 1, 0).toString())) { c.setFont(c.getFont().deriveFont(Font.BOLD)); } return c; } });

5.3 场景三:部署到机房电脑,Win7系统报“找不到JavaFX”

项目纯Swing,但机房JRE常被精简,缺失rt.jar中的Swing类。终极保底方案:用jlink定制最小JRE(JDK 11+):

# 在JDK 11+环境下执行 jlink --module-path $JAVA_HOME/jmods \ --add-modules java.base,java.desktop,java.sql \ --output jre-minimal

生成的jre-minimal目录只有15MB,含Swing/AWT/JDBC必需模块。将StudentSystem.jar和此JRE打包成run.bat:

@echo off jre-minimal\bin\java.exe -jar StudentSystem.jar pause

血泪经验:机房电脑常禁用CMD,所以最终交付物是run.exe(用Launch4j打包),图标换成学校Logo,右键属性里写“双击运行——XX大学教务系统V1.0”。

我带过的课设里,95分以上的共同点不是代码多炫,而是每个按钮点击后,数据库、界面、日志三者状态严格一致。比如退课按钮,必须同时:删selection表记录、刷新JTable、弹出“退课成功”提示、控制台打印DELETE FROM selection WHERE id=123。这种确定性,才是答辩时老师点头的原因。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 7:44:33

Java Servlet + MySQL声纹识别后台源码详解与部署避坑指南

简介&#xff1a;面向Java Web开发者与声纹识别技术学习者的一套完整后台源码&#xff0c;基于Java Servlet和MySQL实现声纹数据的采集、存储、查询与匹配验证&#xff0c;可支撑安全认证、门禁考勤等身份核验场景&#xff1b;适合具备一定Java基础、想理解Web前后端协作与声纹…

作者头像 李华
网站建设 2026/10/26 7:44:01

Windows内核架构与系统调用机制深度解析

1. Windows内核架构深度解析Windows内核作为操作系统的核心引擎&#xff0c;其设计哲学始终围绕着"微内核"与"混合内核"的平衡。现代Windows版本采用了一种精妙的混合架构&#xff1a;将最核心的调度、内存管理等服务保留在内核模式&#xff0c;同时将大量…

作者头像 李华
网站建设 2026/10/26 7:43:52

C#毛笔字算法实现:平滑曲线、笔锋与轮廓生成全解析

简介&#xff1a;面向图形处理与数字艺术开发者的C#毛笔字模拟源码包&#xff0c;聚焦笔锋算法与平滑算法的工程实现&#xff0c;可直接编译运行。资源内包含完整的Visual Studio解决方案&#xff0c;共47个文件&#xff0c;以C#源码文件&#xff08;.cs&#xff09;为核心&…

作者头像 李华
网站建设 2026/10/26 7:43:46

快手自动化攻击防御实战与AI安全技术解析

1. 事件背景&#xff1a;快手遭遇的自动化攻击特征分析2023年第三季度&#xff0c;国内头部短视频平台快手披露遭遇大规模自动化攻击事件。根据技术团队事后复盘&#xff0c;攻击呈现出三个典型工业化特征&#xff1a;攻击工具链完整&#xff1a;攻击者使用自研的分布式任务调度…

作者头像 李华
网站建设 2026/10/26 7:43:34

Text-to-CAD技术解析:从自然语言到三维模型的开源实现与实操

前阵子帮客户补一张法兰盖的图&#xff0c;对方在电话里说得挺清楚&#xff1a;直径80的圆盘&#xff0c;厚12&#xff0c;中心孔25&#xff0c;四个螺栓孔8&#xff0c;分度圆直径60。我挂了电话在CAD里老老实实建模&#xff0c;拉伸、打孔、阵列&#xff0c;再检查一遍尺寸&a…

作者头像 李华
网站建设 2026/10/26 7:43:17

Paperclip:基于Node.js的多AI协同工作流编排系统

1. 项目概述&#xff1a;当AI不再是个体工具&#xff0c;而是一支可调度、可协作、可追责的“数字员工团队”你有没有过这种体验&#xff1a;早上打开IDE&#xff0c;Claude在帮你重写一段晦涩的Python逻辑&#xff1b;中午写PRD时&#xff0c;Codex在隔壁Tab里自动生成接口文档…

作者头像 李华