
简介这是一份用于Java课程设计的学生信息管理系统项目基于Eclipse开发环境与MySQL 8.0数据库使用Swing图形界面完成操作交互实现了管理员登录、注册与密码修改以及学生信息的增删改查覆盖了Java课程设计常见的功能考核点适合正在准备课程设计的学生也适合希望练习界面与数据库综合开发的Java学习者。压缩包共85个文件包含15个Java源文件、45个编译后的class字节码文件、18张界面相关图片另有工程配置文件、数据库连接驱动包、配套开发工具与数据库备份整体大小约836MB属于源码、环境与数据库一应俱全的完整项目包。目前已有三千四百六十四人学习使用被众多课程设计者所采用。解压后可直接导入Eclipse运行数据库脚本与开发工具均已打包能够省去繁琐的环境配置时间同时提供完整源码、图片素材与清晰的工程目录便于按需二次修改或局部替换是一份能直接支撑课程考核、答辩演示与期末评分的完整课设方案。1. 用 Eclipse MySQL 8.0.25 做学生信息管理系统课程设计里最稳的组合每年答辩季都能看到一批同学在技术选型上纠结要不要上 Spring Boot、要不要用 Vue 写前端、数据库要不要换 PostgreSQL。其实对于学生信息管理系统这种以增删改查为核心的课程设计Eclipse MySQL 8.0.25 Swing 这套老组合反而最不容易翻车。Eclipse 对 JDK 版本宽容MySQL 8.0.25 是教学环境最常见的数据库版本Swing 不需要任何前端知识就能画出可交互的桌面界面。这套方案刚好覆盖 Java 基础语法、JDBC、GUI 事件处理、数据库设计四块核心考点适合刚学完 Java 基础、准备做第一个完整项目的同学也适合需要在两三周内交作业的课程设计场景。2. 环境搭建JDK、Eclipse 与 MySQL 8.0.25 的版本匹配和驱动引入2.1 先定 JDKEclipse 版本与 JDK 的对应关系课程设计的环境搭建往往卡在第一步Eclipse 装好了新建项目却报编译级别不对或者无法加载主类。原因多半是 JDK 与 Eclipse 版本不匹配。常见的做法是先用java -version确认当前 JDK 版本再选择对应的 Eclipse 版本。Eclipse 2020-12 到 2021-03 这一批既能用 JDK 8 运行也能用 JDK 11 运行是目前课程设计最稳的选择。JDK 8 的兼容性最好Swing API 在 JDK 8 里已经非常成熟网上能找到的 Java 课程设计参考资料也大多基于 JDK 8。如果机器上已经装了多个 JDK需要在 eclipse.ini 里显式指定。这个文件在 Eclipse 安装目录下用文本编辑器打开后找到-vm配置段-vm C:/Program Files/Java/jdk1.8.0_281/bin/javaw.exe --launcher.appendVmargs -vmargs -Dosgi.requiredJavaVersion1.8-vm后面的路径必须指向具体 JDK 的javaw.exe不能只写目录。osgi.requiredJavaVersion告诉 Eclipse 你要求的最低 JDK 版本写成 1.8 能避免新版 Eclipse 强行要求高版本 JDK 的情况。配置完后在 Eclipse 的 Window - Preferences - Java - Installed JREs 里添加一次 JDK 路径并把项目右键 Properties - Java Compiler 里的编译级别设置为 1.8。这一步不做好后面写 Swing 代码时会出现一大堆方法签名对不上的玄学问题其实不是代码错了是编译级别错了。2.2 MySQL 8.0.25 安装字符集与认证插件两个必改参数MySQL 8.0.25 的安装包在官网下载安装过程中有两个选项会影响后面的开发建议直接改掉。第一个是字符集安装类型选 Server only 之后配置界面里把 Character Set 从默认的 latin1 改成 utf8mb4。第二个是认证插件默认是 caching_sha2_password这个插件在 JDBC 连接时需要额外的公钥交换参数课程设计阶段为了省事可以切成 mysql_native_password。如果安装时没改也可以在安装完成后通过命令行调整ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;mysql_native_password是 MySQL 5.x 时代就有的认证方式兼容所有版本的 JDBC 驱动。caching_sha2_password 安全性更高但对驱动版本和连接参数敏感后面第 3 章会讲到。安装完成后在命令行执行mysql --version输出里包含 mysql Ver 8.0.25 就说明安装成功。另外提醒一句MySQL 8.0.25 安装时设置的 root 密码如果忘了后面所有 JDBC 连接测试都会失败第一次做课程设计我就在这上面踩过坑建议把密码写在一个本地的配置文本里避免答辩前临时改密码导致整套系统连不上库。2.3 用 Eclipse 新建 Java 项目并引入 mysql-connector-j 驱动MySQL 8.0.25 对应的 JDBC 驱动是 mysql-connector-java-8.0.25.jar注意 8.x 版本的驱动类名是com.mysql.cj.jdbc.Driver不是 5.x 时代的com.mysql.jdbc.Driver。在 Eclipse 里新建一个空的 Java 项目然后把下载好的 jar 包复制到项目根目录下的 lib 文件夹里右键项目 - Build Path - Add JARs把 lib 下的驱动加进去。为了验证环境是否通写一个最小的连接测试类import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class TestConnection { public static void main(String[] args) { String url jdbc:mysql://localhost:3306/student_db ?useSSLfalseserverTimezoneAsia/Shanghai characterEncodingutf8allowPublicKeyRetrievaltrue; String user root; String password 你自己的密码; try (Connection conn DriverManager.getConnection(url, user, password)) { System.out.println(连接成功 conn.getCatalog()); } catch (SQLException e) { e.printStackTrace(); } } }这个测试类里最关键的是连接串参数。useSSLfalse关掉 SSL 加密避免本机连接时因为证书问题报错serverTimezoneAsia/Shanghai指定时区MySQL 8.0 对时间类型要求明确时区不写会报 CST 时区无法识别的错误characterEncodingutf8保证中文写入数据库不乱码allowPublicKeyRetrievaltrue是配合 MySQL 8.0 默认认证插件使用的如果安装时已经切到了 mysql_native_password这个参数可以不加。驱动加载的Class.forName(com.mysql.cj.jdbc.Driver)在 JDBC 4.0 之后可以省略但显式写上能让评委一眼看到你理解驱动机制课程设计里不算冗余代码。3. 数据库层学生信息管理系统的表结构、初始化数据与 JDBC 工具类3.1 三张表的关系学生、课程、成绩怎么设计外键学生信息管理系统如果只做单表看起来省事但课程设计的评分标准里一般都有数据库设计合理这一项。常见的做法是拆三张表学生表存基础信息课程表存课程信息成绩表存学生和课程的关联分数。为什么不把成绩直接放进学生表假设一个学生选了五门课学生表里就得预留五个成绩字段没选的课空着选了六门课的人又不够用而且统计某门课的平均分时要扫描整张学生表。拆成三张表之后成绩表通过外键分别引用学生和课程的主键语义清晰也方便写 SQL 统计。表与表的关系是典型的多对多一个学生可以选多门课一门课可以被多个学生选成绩表就是中间表。外键约束一定要加上否则插入成绩时可以乱填 student_id数据完整性全靠代码保证这在答辩时容易被追问。课程设计场景下不需要过度设计这三张表已经能把主键、外键、唯一约束、默认值、自增列这几个数据库核心概念都体现出来。3.2 初始化 SQL建库、建表、插入测试数据一条龙用 SQL 脚本初始化数据库比用 Navicat for MySQL 手工点界面建表更利于复现。以下是课程设计常用的初始化脚本CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4; USE student_db; CREATE TABLE t_student ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 学生主键, student_no VARCHAR(20) NOT NULL UNIQUE COMMENT 学号, name VARCHAR(50) NOT NULL COMMENT 姓名, gender TINYINT NOT NULL DEFAULT 1 COMMENT 性别1男 0女, age INT NOT NULL DEFAULT 0 COMMENT 年龄, phone VARCHAR(20) DEFAULT COMMENT 手机号, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生表; CREATE TABLE t_course ( id INT PRIMARY KEY AUTO_INCREMENT, course_no VARCHAR(20) NOT NULL UNIQUE COMMENT 课程编号, course_name VARCHAR(100) NOT NULL COMMENT 课程名称, credit DECIMAL(3,1) NOT NULL DEFAULT 0.0 COMMENT 学分 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT课程表; CREATE TABLE t_score ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, course_id INT NOT NULL, score DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT 成绩, FOREIGN KEY (student_id) REFERENCES t_student(id), FOREIGN KEY (course_id) REFERENCES t_course(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT成绩表; INSERT INTO t_student (student_no, name, gender, age, phone) VALUES (2023001, 张伟, 1, 20, 13800000001), (2023002, 李娜, 0, 21, 13800000002), (2023003, 王强, 1, 20, 13800000003); INSERT INTO t_course (course_no, course_name, credit) VALUES (C001, Java程序设计, 3.0), (C002, 数据库原理, 2.5); INSERT INTO t_score (student_id, course_id, score) VALUES (1, 1, 88.5), (1, 2, 76.0), (2, 1, 92.0), (3, 2, 65.5);脚本里需要注意的细节数据库和所有表的字符集都指定为 utf8mb4这是 MySQL 8.0 时代最稳妥的中文存储方案。gender字段用 TINYINT 而不是 CHAR(2) 存男/女因为性别是一个枚举含义的值用数字在代码里映射更符合编程习惯。create_time设置 DEFAULT CURRENT_TIMESTAMP插入数据时不需要显式赋值这个细节能在答辩时展示你对 MySQL 函数和默认值机制的了解。外键约束写在建表语句里比后期 ALTER TABLE 添加更清晰也方便评分老师直接看表结构理解关系。3.3 JDBC 工具类连接串参数的逐项说明每次操作数据库都写一遍 DriverManager.getConnection 会让代码非常冗余常见的做法是抽一个 JdbcUtil 工具类。这个类负责加载驱动、获取连接和关闭资源import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JdbcUtil { private static final String URL jdbc:mysql://localhost:3306/student_db ?useSSLfalseserverTimezoneAsia/Shanghai characterEncodingutf8allowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 你的密码; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, Statement stmt, ResultSet rs) { try { if (rs ! null) rs.close(); } catch (SQLException ignored) {} try { if (stmt ! null) stmt.close(); } catch (SQLException ignored) {} try { if (conn ! null) conn.close(); } catch (SQLException ignored) {} } }工具类里的 URL 参数是 MySQL 8.0.25 连接的重中之重。useSSLfalse在高版本 MySQL 里必须显式声明否则驱动会尝试建立 SSL 连接导致握手失败。serverTimezone指定为 Asia/Shanghai解决了 MySQL 8.0 时区偏移量的报错。characterEncodingutf8与数据库端的 utf8mb4 配合确保中文从界面到数据库全程不出现问号。allowPublicKeyRetrievaltrue只在使用 caching_sha2_password 时需要如果你安装时切换成了 mysql_native_password删掉这个参数也能正常连接。PASSWORD 直接写在代码里对课程设计来说可以接受但养成从配置文件读取的好习惯会在答辩时加分比如用Properties类加载一个 db.properties 文件。4. Swing 界面与增删改查从登录窗口到学生表格的完整链路4.1 登录窗体组件布局、回车监听与密码校验Swing 界面的起点通常是一个登录窗体。用 JFrame 作为顶层窗口在构造函数里设置标题、大小、关闭行为然后逐个添加 JLabel、JTextField、JPasswordField 和 JButton。布局管理器的选择上初学者用绝对布局setLayout(null) setBounds最容易上手但界面缩放时会错位用 GridBagLayout 又太复杂。折中方案是使用 GridLayout 或 BoxLayout 把组件按行排列既不需要精确计算坐标也不会因为分辨率变化而乱掉。登录按钮的事件处理是重点要给按钮注册 ActionListener用 lambda 表达式写最简洁JButton loginBtn new JButton(登录); loginBtn.addActionListener(e - { String username userField.getText().trim(); String password new String(pwdField.getPassword()); if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(LoginFrame.this, 用户名和密码不能为空); return; } if (checkLogin(username, password)) { new MainFrame().setVisible(true); dispose(); } else { JOptionPane.showMessageDialog(LoginFrame.this, 用户名或密码错误); } });pwdField.getPassword()返回的是 char[] 而不是 String这样做是为了避免密码字符串留在内存里被反射方式窃取写代码时记得用 new String 包装一下再比较。回车触发登录是很多同学忽略的交互细节给 userField 添加userField.addActionListener(e - loginBtn.doClick())就能实现让用户输完密码按回车直接登录这个小功能在演示时很讨喜。checkLogin 方法里先查数据库再返回 boolean如果数据库连接失败要在 catch 里给用户一个明确的提示不能只打印堆栈否则演示时连接断了界面没有任何反馈。4.2 主窗体JTabbedPane 页签与学生管理面板登录成功之后进入主窗体主窗体用 JFrame 承载中间放一个 JTabbedPane把学生管理课程管理成绩管理分成多个页签。即使课程设计只要求做学生信息管理也可以在主窗体预留一个成绩管理空页签并加上提示显示出系统是可扩展的。学生管理页签内部再拆分上面是查询条件区域中间是 JTable 学生列表下面是一排操作按钮这是典型的 Swing CRUD 布局。public class MainFrame extends JFrame { private JTabbedPane tabPane; private StudentPanel studentPanel; public MainFrame() { setTitle(学生信息管理系统); setSize(900, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); tabPane new JTabbedPane(); studentPanel new StudentPanel(); tabPane.addTab(学生管理, studentPanel); tabPane.addTab(课程管理, new JPanel()); tabPane.addTab(成绩管理, new JPanel()); setContentPane(tabPane); } }setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)表示点击窗口关闭按钮时退出进程必须在主窗体设置登录窗体的关闭动作如果用 EXIT_ON_CLOSE那么登录窗口一关整个程序就退出了后面的主窗体永远见不到。setLocationRelativeTo(null)让窗口居中显示这在投影演示时比默认的左上角位置更专业。每个页签对应一个独立 JPanel 子类比如 StudentPanel这样界面逻辑按模块隔离后续增删改查都在 StudentPanel 里操作不会把代码全塞进 MainFrame 变成几百行的面条代码。4.3 JTable 显示学生列表DefaultTableModel 的填充与刷新JTable 本身不负责数据存储它通过 TableModel 接口获取数据。课程设计最常见的实现方式是使用 DefaultTableModel它的addRow和setRowCount(0)方法可以很方便地刷新数据。每次查询完先清空旧数据再逐行填充新数据这是防止数据残留的关键操作String[] columns {ID, 学号, 姓名, 性别, 年龄, 手机号}; DefaultTableModel model new DefaultTableModel(columns, 0); JTable table new JTable(model); private void loadData() { model.setRowCount(0); ListStudent list studentDao.findAll(); for (Student s : list) { model.addRow(new Object[]{ s.getId(), s.getStudentNo(), s.getName(), s.getGender() 1 ? 男 : 女, s.getAge(), s.getPhone() }); } }new DefaultTableModel(columns, 0)的第二个参数 0 表示初始行数为 0表头由第一个参数的数组决定。model.setRowCount(0) 是清空表格最稳妥的方法比table.removeAll()靠谱得多。性别字段从数据库读出来是 0 或 1在界面层映射成男女数据转换放在视图层是合理的不要让 DAO 层去拼这种展示字符串。JTable 默认是可编辑的如果不想让用户直接在表格里改数据需要重写isCellEditable方法返回 false否则会出现单元格可以输入、但一刷新又还原的诡异现象。4.4 新增、修改、删除表单校验、PreparedStatement 与二次确认新增和修改功能通常用一个弹出对话框完成对话框里放若干 JLabel 和 JTextField。新增时学号和姓名必填年龄和手机号可以不填校验逻辑放在提交按钮的事件里。提交时调用 StudentDao 的 insert 方法public int insert(Student s) { String sql INSERT INTO t_student (student_no, name, gender, age, phone) VALUES (?, ?, ?, ?, ?); try (Connection conn JdbcUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, s.getStudentNo()); ps.setString(2, s.getName()); ps.setInt(3, s.getGender()); ps.setInt(4, s.getAge()); ps.setString(5, s.getPhone()); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } }PreparedStatement 用占位符?替代直接拼接 SQL第一个好处是防止 SQL 注入学号里输入一段or 11之类的字符串也不会改变查询语义第二个好处是参数类型明确setInt、setString 让数据库驱动做类型转换比字符串拼接后隐式转换更可靠。修改操作和新增很像只是 SQL 变成UPDATE t_student SET student_no?, name?, ... WHERE id?注意 WHERE 条件必须带主键 id这个 id 来源于用户在表格上选中的那一行。删除操作在课程设计里被扣分最多的点是没有二次确认直接点了就删演示时手滑删掉一条数据非常尴尬int row table.getSelectedRow(); if (row 0) { JOptionPane.showMessageDialog(this, 请先选中要删除的行); return; } int id (Integer) model.getValueAt(row, 0); int confirm JOptionPane.showConfirmDialog(this, 确定删除学号为 model.getValueAt(row, 1) 的学生吗, 删除确认, JOptionPane.YES_NO_OPTION); if (confirm JOptionPane.YES_OPTION) { studentDao.deleteById(id); loadData(); }选择表格行时用getSelectedRow()返回 -1 表示没选中要提前判断并提示。删除的确认框用 showConfirmDialog 的 YES_NO_OPTION用户点是才执行删除。这里有个细节删除成功后马上调用 loadData() 刷新表格这是 Swing 数据刷新的标准动作很多同学删除后表格不更新就是因为忘了重新查询数据库。4.5 模糊查询按学号或姓名的参数化 like 实现查询条件区域一般放一个 JTextField 和一个查询按钮输入关键字后按学号或姓名模糊匹配。模糊查询的 SQL 写法是WHERE student_no LIKE ? OR name LIKE ?PreparedStatement 传参时把通配符拼在参数里public ListStudent search(String keyword) { String sql SELECT id, student_no, name, gender, age, phone FROM t_student WHERE student_no LIKE ? OR name LIKE ? ORDER BY id; ListStudent list new ArrayList(); String likePattern % keyword.trim() %; try (Connection conn JdbcUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, likePattern); ps.setString(2, likePattern); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { Student s new Student(); s.setId(rs.getInt(id)); s.setStudentNo(rs.getString(student_no)); s.setName(rs.getString(name)); list.add(s); } } } catch (SQLException e) { e.printStackTrace(); } return list; }通配符%放在参数里而不是 SQL 语句里拼是因为 PreparedStatement 的占位符会被驱动转义如果把%直接写进 SQL 变成% ? %就会语法错误。LIKE 的 OR 条件在数据量小的时候没有问题但如果表里数据过万这个查询不走索引会变慢课程设计阶段不需要考虑这个性能问题但如果答辩被问到可以说数据量大时可以改为用 UNION 拆分两个查询分别走学号和姓名的普通索引。查询完之后同样要调用 loadData 的模型更新逻辑把表格内容替换成新结果。5. 避坑排查学生信息管理系统最常见的 5 个翻车现场5.1 JDBC 连接报错Public Key Retrieval is not allowed现象连接测试时驱动抛出异常堆栈里有Public Key Retrieval is not allowed字样连接失败。原因MySQL 8.0 默认的认证插件是 caching_sha2_password客户端第一次连接需要向服务端请求公钥来加密密码而 JDBC 驱动的默认行为是拒绝自动获取公钥于是抛出这个错误。解决在 JDBC 连接串里加allowPublicKeyRetrievaltrue。如果安装 MySQL 时已经改成了 mysql_native_password这个错误不会出现。我一般建议两个方案都保留连接串里写上这个参数安装时顺手把默认插件改成 mysql_native_password双保险遇到教室电脑里的 MySQL 5.x 也不会因为驱动版本不兼容而卡住。5.2 中文乱码界面显示问号或数据库存的是问号现象Swing 界面上输入中文点保存后再查出来全是 ? 号或者数据库里字段值正常界面显示乱码。原因字符集链路有四层任何一层不是 utf8 都会出问题。最常被忽略的是项目源码文件的编码Eclipse 默认可能是 GBK写进去的中文字面量是 GBK 编码而数据库按 utf8mb4 解析自然乱码。同时 MySQL 建库时如果没指定 DEFAULT CHARACTER SET utf8mb4默认继承实例的 latin1。解决按顺序排查四层。第一Eclipse 的 Window - Preferences - General - Workspace 里把 Text file encoding 改为 UTF-8。第二数据库和连接串都指定 utf8mb4 / utf8如第 3 章初始化脚本所示。第三JDBC URL 里加characterEncodingutf8。第四如果已经插入的是乱码数据直接删除重插不要试图原地修复。5.3 eclipse 提示找不到或无法加载主类现象写完一个类点 Run As - Java ApplicationEclipse 弹出对话框提示找不到或无法加载主类代码在别的环境明明能跑。原因多数情况是主类的源文件没被编译到 bin 目录或者 run 配置里指定的项目错了。这个报错在 Eclipse 里还有一个常见的变体是从 Web 项目模板继承来的启动配置试图用服务器模式启动普通 Java 类。解决右键项目 - Properties - Java Build Path - Source确认 src 目录被标记为源文件夹bin 目录作为输出目录存在。然后右键要运行的主类选择 Run As - Java Application不要选别的启动方式。如果还是不识别主类Project - Clean 重新编译一次。这个动作能解决 Eclipse 里八成以上的编译状态错乱问题。5.4 数据库改了数据JTable 不刷新现象登录系统后列表显示 5 条数据在另一个窗口往数据库里插入一条回到系统点查询表格还是 5 条甚至系统内新增了一条表格底部也不出现新行。原因JTable 的数据源是 DefaultTableModel查询按钮的监听器里只执行了 SQL没有把查询结果重新 set 给模型。Swing 的 JTable 不会主动感知数据库变化必须手动触发模型更新。解决所有对数据库的写操作完成后统一调用一次 loadData() 方法里面先model.setRowCount(0)清空再model.addRow(...)填充最新结果。修改和删除操作同样要在执行完 SQL 后重新 loadData这是 Swing CRUD 的固定动作。如果写的是批量操作注意要等事务提交后再刷界面否则可能读到旧数据。5.5 MySQL 服务启动失败或 3306 端口被占用现象服务管理器里启动 MySQL 报错或者应用启动时 JDBC 连接报Cant connect to local MySQL server on socket、connect timed out之类。原因3306 端口被其他程序占用最常见的占用者是自己之前装过的 MySQL 实例、XAMPP 自带数据库、或者后门程序系统残留。也可能是连接串写的是localhost而服务监听的是127.0.0.1在某些 Linux 环境下 socket 路径不一致。解决命令行执行netstat -ano | findstr 3306查看占用进程的 PID再通过任务管理器确认是不是残留的 mysqld。如果是关闭占用进程或者把当前 MySQL 服务的端口改成 3307同时修改 JDBC URL 里的端口号。如果是 socket 问题Windows 下连接串改为jdbc:mysql://127.0.0.1:3306/student_db绕过本地 socket 解析通常能解决。6. 从能跑到能答辩给系统加上验证、打包和演示脚本课程设计做到能跑只完成了 60 分答辩现场的演示流畅度决定剩下 40 分。第一个技巧是给 DAO 层写一个简单的 JUnit 测试类不需要覆盖全部方法只要把增删改查各测一条路径答辩时打开测试运行结果比口头解释有说服力得多。JUnit 4 需要右键项目添加 JUnit 4 库测试类里标注Test注解Test public void testFindAndInsert() { StudentDao dao new StudentDao(); ListStudent before dao.findAll(); Student s new Student(null, 2023999, 测试生, 1, 18, 13900000000); dao.insert(s); ListStudent after dao.findAll(); System.out.println(增加前后数据量 before.size() - after.size()); org.junit.Assert.assertEquals(before.size() 1, after.size()); }导出可运行 JAR 时右键项目 - Export - Runnable JAR File启动配置里选中 MainFrame 或 LoginFrameLibrary handling 选Extract required libraries into generated JAR。这样导出的 JAR 双击就能运行前提是 JDBC 驱动被正确打进包里。答辩演示的顺序建议固定成登录 - 查询全部学生 - 按姓名模糊查询 - 新增一条数据 - 修改该数据 - 删除该数据 - 关闭系统重开验证数据确实持久化。这个顺序覆盖了所有核心功能不会现场现想操作步骤。最后说点血泪经验。我当年做课程设计时最懊悔的是没有在每次数据库操作后重新加载表格答辩演示新增功能时数据死活不刷新评委一眼看出代码缺陷。从那以后我养成了一个习惯所有写操作的方法执行完最后一行必然是调用查询方法来刷新界面。这个习惯比任何框架都管用。希望帮到你。本文还有配套的精品资源点击获取