
简介这是一套面向Java课程设计的实验室设备管理系统源码包适合正在完成SwingMySQL课设的在校生作为参考蓝本。系统围绕设备管理典型业务流程展开包含登录注册、管理员与普通用户双角色主界面以及按设备名称、当前状态如正常/报废筛选查询和新增、修改、删除等功能通过JDBC完成对MySQL数据库的读写操作整体可直接编译运行也可继续扩展。压缩包共72个文件、约350KB其中包含13个Java源文件、36个编译后的class文件、1个数据库初始化脚本、11张PNG图片与9个XML工程配置文件从源码到数据库脚本的配套链条完整。目前已有159人学习下载属于典型课设规模的小型项目对于想理解Swing窗体设计与JDBC数据库交互流程的读者有直接帮助。配合包内数据库脚本可直接导入数据并启动系统节省从零搭建环境的时间同时其朴素的界面风格也更贴合高校课程设计的验收尺度。1. 实验室设备管理系统为什么它是 Java 课设里最稳的 Swing MySQL 选题实验室设备管理系统是 Java 课设里出现频率最高的题目之一因为它覆盖了 Swing 图形界面、JDBC 数据库访问、增删改查和多角色登录这些必考点逻辑却不复杂。这份资源是完整可运行工程压缩包内含全部 Java 源码和 sysb.sql 数据库脚本从 Login 到 AdminMain、UserMain 一共 13 个类构成设备管理的完整闭环。我接单开发的系统大多是这种形态Swing 原生组件拼界面JDBC 直连 MySQL不套框架。课设老师关心的是你能不能讲清每个按钮背后的 SQL 与 Java 调用关系界面太漂亮反而容易被怀疑。所以这个项目的「朴素感」恰恰是它的优点——答辩时每个类、每段 SQL 都能对应上。它适合正在做 Java 课设、需要一套能跑通又能讲明白的参考实现的人也适合想读懂完整 Swing MySQL 项目协作方式的新手。下面我按源码包里的实际文件拆解结构、关键逻辑和排错步骤。2. 项目骨架拆解sysb.sql 建表与 JDBCUtils 连接参数2.1 从 sysb.sql 反推数据模型设备表与状态字段压缩包根目录下的 sysb.sql 是唯一的数据库脚本建库、建表、初始数据一次性全在里面。数据库名 sysb 和工程 .iml 文件同名说明整套代码就是围绕这一个库跑的。拿到资源后我建议先读脚本再读代码——脚本里每张表都对应一个或几个 Java 类表结构理解了代码读起来就是顺水推舟。从源码类名能反推出表结构SelectByBFZT 里的 BFZT 是「报废状态」SelectBySBZT 里的 SBZT 是「设备状态」。也就是说设备主表至少有两个状态列一个管设备当前能否借用一个管是否报废。这是实验室设备管理系统里的通行设计——设备正常、借用中、维修中是一个维度报废与否是另一个维度两个维度互不干扰查询时单独过滤。再加上 Register、Login 用到的用户表整个库基本就是「设备表 用户表 借还记录」的规模。下面是我按这套代码的常见形态补的建表示例实际脚本里列名可能有差异但语义一致CREATE DATABASE IF NOT EXISTS sysb DEFAULT CHARACTER SET utf8mb4; USE sysb; DROP TABLE IF EXISTS equipment; CREATE TABLE equipment ( id INT PRIMARY KEY AUTO_INCREMENT, equip_name VARCHAR(100) NOT NULL COMMENT 设备名称, equip_model VARCHAR(50) COMMENT 型号规格, equip_loc VARCHAR(100) COMMENT 存放位置, equip_status VARCHAR(20) DEFAULT 可用 COMMENT 设备状态可用/借用中/维修中, bfzt VARCHAR(20) DEFAULT 未报废 COMMENT 报废状态未报废/已报废 ); DROP TABLE IF EXISTS sys_user; CREATE TABLE sys_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(50) NOT NULL, role VARCHAR(20) DEFAULT 普通用户 );两个细节值得记下来。字符集必须用 utf8mb4否则插入中文设备名会变成问号状态字段用中文枚举而不是数字SQL 直读性好下拉框选中「可用」就能直接拼进 WHERE 条件。用 Navicat 或 MySQL Workbench 打开整个脚本执行后左侧表列表里能看到 equipment、sys_user 才算初始化完成。提示拿到 sql 脚本后不要只跑一半。执行完确认表确实生成再继续配置 Java 工程否则后面所有报错都会指向「表不存在」。2.2 JDBCUtils连接参数集中在这一处改整个工程没有框架数据库访问全靠 JDBCUtils 这个工具类撑着。它的职责是静态代码块加载驱动、getConnection() 返回连接、close() 统一释放资源。这种封装在课设里已经算有工程意识了——13 个业务类谁都不需要自己写 Class.forName改连接参数只动这一个文件。import java.sql.*; public class JDBCUtils { private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/sysb ?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf-8; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException ignored) {} } if (ps ! null) { try { ps.close(); } catch (SQLException ignored) {} } if (conn ! null) { try { conn.close(); } catch (SQLException ignored) {} } } }三个参数要重点说明。DRIVER 是 com.mysql.cj.jdbc.Driver这是 MySQL 8 的驱动类名如果你本地是 MySQL 5.7要改成 com.mysql.jdbc.Driver否则 Class.forName 直接抛类找不到。URL 里的 serverTimezoneAsia/Shanghai 是 MySQL 8 的硬性要求不加就报时区错误characterEncodingutf-8 配合建库的 utf8mb4解决中文乱码。USER 和 PASSWORD 是课设运行时第一个要改的地方必须换成你本机 MySQL 的实际账号密码。这套写法不算连接池但已经能看到连接池思想的雏形。答辩时如果老师问「为什么不直接用连接池」你可以说课设规模用 DriverManager 够用并顺势说出连接池是复用连接、避免频繁创建销毁的思路——这一句就能把知识深度拉上来。2.3 Start 入口与登录注册一个库两个界面怎么分流工程入口是 Start.java通常是一个带标题的 JFrame放一个进入按钮或者直接 new Login()。从 Login.java、Register.java 的存在能看出权限模型注册时选择身份管理员/普通用户登录后根据角色决定打开 AdminMain 还是 UserMain。两个主界面的差别在菜单项AdminMain 通常有设备添加、删除、报废审核等管理操作UserMain 只保留查询和借用归还。这种「一个数据库、两个界面、菜单不同」的设计在答辩时非常好讲老师问权限怎么控制的你就说登录结果里带 role 字段主界面用 if 判断实例化哪个窗口。public class Login extends JFrame { private void doLogin() { String sql SELECT role FROM sys_user WHERE username? AND password?; try (Connection conn JDBCUtils.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, userField.getText().trim()); ps.setString(2, new String(passField.getPassword())); ResultSet rs ps.executeQuery(); if (rs.next()) { if (管理员.equals(rs.getString(role))) { new AdminMain().setVisible(true); } else { new UserMain().setVisible(true); } dispose(); } else { JOptionPane.showMessageDialog(this, 用户名或密码错误); } } catch (SQLException e) { e.printStackTrace(); } } }密码框用 getPassword() 返回 char[] 而不是 getText()这是 Swing 的规范习惯答辩时主动提一句是加分项。登录查询用的是 PreparedStatement 加占位符 ?这也是整包代码的统一风格——后面所有增删改查全是这个套路没有一处直接拼 SQL 字符串。try-with-resources 自动关闭 Connection 和 PreparedStatement配合 JDBCUtils 里的 close()资源释放讲起来很干净。3. 增删改查实现Add、Update、Delete 与五个查询类怎么协作3.1 Add / Update / Delete预编译语句与受影响行数新增、修改、删除是三个独立类逻辑结构几乎一样取界面输入、拼 SQL、执行 executeUpdate、用 JOptionPane 弹结果、刷新表格。因为结构相似有人直接复制 Add 的代码改个 SQL 当 Update 用——能跑但字段必须取全否则更新后会出现部分列被覆盖成空值。public class Add extends JFrame { private void doAdd() { String sql INSERT INTO equipment(equip_name, equip_model, equip_loc, equip_status) VALUES(?, ?, ?, ?); try (Connection conn JDBCUtils.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, nameField.getText().trim()); ps.setString(2, modelField.getText().trim()); ps.setString(3, locField.getText().trim()); ps.setString(4, statusCombo.getSelectedItem().toString()); int rows ps.executeUpdate(); if (rows 0) { JOptionPane.showMessageDialog(this, 添加成功); refreshTable(); } } catch (SQLException e) { e.printStackTrace(); } } private void refreshTable() { // 调用 SelectAll 的查询方法把最新数据重新装进 JTable } }executeUpdate 返回受影响行数insert 成功返回 1这是判断操作是否生效的标准姿势。用 PreparedStatement 而不是 Statement 直接拼字符串的原因有两点一是字符串里的引号和中文符号会被当成 SQL 语法解析拼错一个单引号直接 SQLException二是防注入虽然课设不强调安全但这是答辩老师最爱问的点。setString 的索引从 1 开始顺序必须和 SQL 里问号出现的顺序一致这是最容易看走眼的低级错误。Update 和 Delete 的差别只在 SQL 带不带 WHERE id?。Delete 执行前建议加一个确认对话框用 JOptionPane.showConfirmDialog 返回 YES_OPTION 才执行删除这个交互细节在演示时非常显眼属于「别人没做你做了」的小亮点。3.2 SelectByName 与 SelectAll模糊查询和 JTable 刷新SelectAll 是设备列表页面的数据源不带条件查询所有设备行SelectByName 按名称筛选SQL 用 LIKE 实现模糊匹配。这两个类合起来就是「列表展示 条件过滤」的完整范例。public class SelectByName extends JFrame { private void doSearch() { String keyword keywordField.getText().trim(); String sql SELECT id, equip_name, equip_model, equip_loc, equip_status, bfzt FROM equipment WHERE equip_name LIKE ?; try (Connection conn JDBCUtils.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); ResultSet rs ps.executeQuery(); DefaultTableModel model (DefaultTableModel) table.getModel(); model.setRowCount(0); // 清掉上一次查询的残留行 while (rs.next()) { model.addRow(new Object[]{ rs.getInt(id), rs.getString(equip_name), rs.getString(equip_model), rs.getString(equip_loc), rs.getString(equip_status), rs.getString(bfzt) }); } } catch (SQLException e) { e.printStackTrace(); } } }LIKE 模糊查询的关键是占位符里拼接 %ps.setString(1, % keyword %)这样关键字在名称开头、中间还是结尾都能命中。很多新手把 % 直接写进 SQL 字符串的引号里结果 keyword 变成字面量「%keyword%」查询永远为空。model.setRowCount(0) 这行是必写项——不写的话第二次查询会在旧数据后面继续追加行表格越查越长这是 Swing JTable 最常见的翻车现场。一个容易忽略的点JTable 的数据模型要固定。table 初始化时用 new DefaultTableModel(columnNames, 0) 创建查询时强转成 DefaultTableModel 才能安全 addRow、setRowCount。如果 table 是用 NetBeans 拖出来的模型类型可能不同强转前先确认类型否则会抛 ClassCastException。3.3 BFZT / SBZT 状态查询下拉框与 WHERE 条件的映射SelectByBFZT 和 SelectBySBZT 是这套系统里最有业务味的两个类。BFZT 报废状态、SBZT 设备状态界面通常是一个 JComboBox 加查询按钮下拉框选项写死为「可用、维修中、已报废」或「未报废、已报废」。String status statusCombo.getSelectedItem().toString(); String sql SELECT * FROM equipment WHERE bfzt ?; if (全部.equals(status)) { sql SELECT * FROM equipment; // 不带 WHERE } else { ps.setString(1, status); }这里有个隐蔽的坑下拉框的显示文本和数据库里存的值必须完全一致包括空格和标点。比如界面上显示「已 报 废」中间带了空格SQL 永远匹配不上看起来就像「查询失灵」的玄学 bug。我一般习惯在界面初始化时用数据库里查出来的 distinct 值直接填充下拉框而不是手敲选项这样显示值和存储值天然一致。状态查询是最能体现「业务需求转 SQL」的模块。答辩时顺带讲一句「设备状态和报废状态分开存是因为一台维修中的设备可能已经报废两个维度不能合并成一个字段」——这句话直接展示你理解业务而不是只会写代码。4. 避坑手册课设跑不动的五个高频报错与排查顺序先说排查顺序的原则先环境后代码先连接后 SQL。课设里 80% 的报错集中在驱动、时区、编码、表结构这四类代码本身的逻辑错误反而最少。下面五个问题按我经手项目的出现频率排序可以对着报错信息直接查。报错关键信息大概率原因ClassNotFoundException: com.mysql.cj.jdbc.Driver驱动 jar 没进 classpathCommunications link failureMySQL 服务没启动time zone value ... is unrecognizedURL 缺 serverTimezone中文显示 ???字符集三层不一致Table sysb.xxx doesnt existsql 脚本没执行或选错库4.1 java.lang.ClassNotFoundExceptionmysql 驱动没进构建路径现象编译能通过一运行就报 ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因mysql-connector-java 的 jar 包没加入工程的构建路径。很多人把 jar 拷进了项目目录但 IDEA 里没执行 Add as Library驱动类根本不在 classpath 里。解决IDEA 里右键 jar 文件选择 Add as Library或者 File → Project Structure → Libraries 里添加。Eclipse 则是 Build Path → Configure Build Path → Add External JARs。加完重启运行类即可。这里顺带确认 jar 版本和 JDK 匹配新版驱动要求 JDK 8 以上。4.2 CommunicationsException 与时区错误MySQL 8 的两道坎现象连接数据库时报 The server time zone value ???ú is unrecognized或者 Communications link failure两者经常连续出现。原因MySQL 8 驱动对时区校验变严格URL 没带 serverTimezone 就直接拒连而 Communications link failure 通常是 MySQL 服务没启动或者端口被占用。这两件事症状不同、根源不同但新手容易混为一谈。解决先看任务管理器里 mysqld 进程是否在跑没跑就启动 MySQL 服务再用 Navicat 或命令行测试 root 账号能否登录确认密码没记错最后确认 URL 带了 serverTimezoneAsia/Shanghai。按服务 → 账号 → 参数的顺序排查一般五分钟定位。4.3 中文变问号字符集三层都对上才算完现象插入或查询设备名时中文全部显示成 ???英文和数字正常。原因三层有一层编码没对齐——建库用了默认 latin1、连接 URL 没带 characterEncodingutf-8、或者表结构本身不是 utf8mb4。解决sysb.sql 开头一般已写 CHARACTER SET utf8mb4确认执行时没报错连接 URL 补上 characterEncodingutf-8如果数据已经写坏把表 drop 掉重新执行脚本初始化。不要在已变问号的数据上改字符集那只会越改越乱。我每次初始化完都会先 insert 一条中文记录测试再往下走。4.4 SQLSyntaxErrorException表不存在或列名对不上现象报 Table sysb.equipment doesnt exist或者 Unknown column bfzt in field list。原因最常见的是 sysb.sql 没执行成功或者执行时选错了数据库表建到了别的库下面。其次是表列名和 Java 代码里 rs.getString() 写的列名不一致多一个下划线、大小写不同都会报。解决用 SHOW TABLES; 确认表在 sysb 库里再用 DESC equipment; 对比 Java 代码里取列的字符串。这个检查 30 秒能做完但能省掉一整晚的排查时间。特别提醒表名和列名在 Windows 的 MySQL 里不区分大小写但 Linux 下区分跨环境跑的时候要统一用小写。4.5 点击查询界面假死Swing 事件线程里做了重活现象点「查询全部」按钮后窗口卡住拖不动鼠标转圈几秒后才恢复。原因Swing 的界面事件都跑在 EDTEvent Dispatch Thread上数据库查询是阻塞操作查询期间界面线程被占住窗口自然假死。课设数据量小一般不真死但本地 MySQL 响应慢时会明显卡顿。解决如果只想稳交课设登录进入主界面后先做一次 SelectAll 预加载后续查询都增量刷新如果想在答辩里加分把耗时查询放进 SwingWorker 的 doInBackground()查询完在 done() 里更新表格。SwingWorker 是 Swing 自带的方案不需要引第三方库讲出来属于超出课设要求的亮点。5. 答辩前验证清单数据重置、JTable 刷新与三分钟讲清 JDBC答辩前我习惯按一份固定清单走一遍顺序不变每步都有明确目的。第一把数据库重置到初始状态。执行 DROP DATABASE sysb; 再重新 source sysb.sql保证演示时数据是老师看到的干净状态不残留我调试时乱插的测试行。这一步顺带验证了 sysb.sql 的完整性——如果脚本本身有问题现在暴露比答辩时暴露好一百倍。第二验证三条主链路。管理员登录 → 添加设备 → 在 SelectAll 里看到新行修改设备状态 → 按 SBZT 过滤能查到删除设备 → 确认对话框正常弹出。这条链路顺下来核心功能就没有漏的。第三盯死 JTable 刷新。每次增删改后必须调用一次查询方法重装模型否则表格和数据库不一致演示时会被老师当场指出来。我一般把查询封装成一个方法增删改的成功分支里统一调用代码里留好注释。第四准备一段三分半的「JDBC 六步」讲解。老师最爱问的一句话是「你查一条数据经历了哪些步骤」。标准答案是Class.forName 注册驱动 → DriverManager.getConnection 拿连接 → prepareStatement 预编译 SQL → 设置占位符参数 → executeQuery 或 executeUpdate 执行 → finally 里按 ResultSet、Statement、Connection 顺序关闭资源。把这六步背熟再结合 JDBCUtils 里的 close() 方法讲这一段就稳了。时间允许的话可以现场调两个 Swing 细节table.getColumnModel().getColumn(i).setPreferredWidth() 调整列宽setLocationRelativeTo(null) 让窗口居中。这些改动不涉及逻辑演示时改完立即生效显得对代码非常熟。这套系统我经手交付过很多次习惯一直没变不管时间多紧交之前强制把数据库脚本从头执行一遍、把三条主链路点一遍、把六步 JDBC 背一遍。哪怕代码已经跑过一百次这一步我也没省过因为课设翻车往往不在代码逻辑而在环境残留和版本不一致。希望帮到你。本文还有配套的精品资源点击获取