ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JavaSwing+MySQL+JDBC人事管理系统课设指南:从结构到避坑

JavaSwing+MySQL+JDBC人事管理系统课设指南:从结构到避坑 简介这是一份基于Java Swing、MySQL与JDBC开发的数据库课程设计人事管理系统源码包主要面向计算机相关专业完成数据库课程设计或毕业设计的学生也适合初学者练习桌面应用与MySQL交互。系统包含软件界面覆盖人事信息管理常用功能能帮助学习者理解Swing界面搭建、JDBC连接数据库以及SQL建表与数据操作。包内共有24个文件以11个Java源文件、12张界面运行截图和1个SQL脚本为主可直观对照界面效果与后端代码整体压缩包仅143KB结构简洁便于快速下载与本地部署。发布者提示运行报错多由数据库版本差异引起属于基础问题可自行解决这一说明也适合排查同类环境问题。目前已有3878人学习下载说明这份资源对课程设计场景具有一定参考价值。下载后可用SQL脚本初始化数据库再结合Java代码运行系统借此梳理数据库课程设计的完整流程。1. JavaSwingMySQLJDBC 人事管理系统课设落地前先搞懂这三件事数据库课程设计大概是大学里最需要同时交付代码、演示截图、SQL 脚本三件套的作业。用 JavaSwing 做界面、MySQL 存数据、JDBC 做连接的人事管理系统恰好把这三样一次占全登录窗口、员工管理、部门联动全部是桌面 Java 程序直接操作 MySQL不依赖 Tomcat也不写前端页面。这份资源解压后是 mysqljava 人事管理.zip里面 src 放 Java 源码images 放窗口图标和按钮图sql 目录下是 databaseproject.sql 建库脚本。比较实在的一点是资源自带说明里就写了报的错误基本都是数据库版本不同造成的基础问题。也就是说代码没绕弯子适合拿来复现、改造再补上自己的亮点。适合谁用正在做数据库课程设计或 Java 课程设计的学生以及想找一个完整 SwingJDBC CRUD 链路做参考的初学者。后面几章按「工程结构 → JDBC 连接 → 界面联动 → 避坑 → 进阶」的顺序把这个资源从能打开到能答辩讲清楚。2. 工程结构与 SQL 落地导入脚本前先看清 src、images、sql 的分工很多同学拿到压缩包第一件事就是双击开发工具把 src 整个拖进去结果图标丢失、表不存在、连接报错一个接一个。其实先花十分钟把三个目录看懂后面能省一晚上的排错时间。2.1 压缩包内部结构src、images、sql 目录各自承担什么解压后典型目录结构如下mysqljava人事管理/ ├── src/ # Java 源码 │ ├── view/ # Swing 界面类登录窗、主窗体、员工管理 │ ├── dao/ # 数据访问类员工、部门、登录校验 │ └── util/ # DBHelper 等连接工具 ├── images/ # 窗口图标、按钮背景图、logo └── sql/ └── databaseproject.sql # 建库建表脚本src 目录是代码主体view 放 JFrame 和 JPaneldao 放 JDBC 操作util 放连接工具类。images 目录很容易被忽略但 Swing 界面如果引用了图片路径不对会直接空指针或者按钮上不显示任何图标。sql 目录下的 databaseproject.sql 是整个项目的根基——没有它后面所有查询都会因为表不存在而失败。改动优先级上看如果你只想改项目名、表名、加字段动 src/dao 和 sql 就够了想换皮肤或改图标再动 imagesview 层一般只改按钮事件里的逻辑。2.2 建库脚本导入字段类型、字符集和外键一起处理以 Windows 下 MySQL 8.0 为例先启动服务再命令行登录并导入mysql -u root -p source D:/course/mysqljava人事管理/sql/databaseproject.sql;用 Navicat 也可以新建连接后右键运行 SQL 文件。脚本里的建表语句通常是这个风格CREATE DATABASE IF NOT EXISTS hrm DEFAULT CHARACTER SET utf8mb4; USE hrm; CREATE TABLE tb_dept ( dept_id INT PRIMARY KEY AUTO_INCREMENT, dept_name VARCHAR(50) NOT NULL UNIQUE, remark VARCHAR(200) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE tb_employee ( emp_id INT PRIMARY KEY AUTO_INCREMENT, emp_no VARCHAR(20) NOT NULL UNIQUE, emp_name VARCHAR(30) NOT NULL, gender CHAR(2) DEFAULT 男, dept_id INT, position VARCHAR(50), hire_date DATE, salary DECIMAL(10,2), phone VARCHAR(20), CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES tb_dept(dept_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;表名、字段名以你解压出来的 databaseproject.sql 实际内容为准我列的是人事管理课设最常见结构。参数说明emp_no 用 VARCHAR(20) 是因为员工编号不一定是纯数字可能带字母前缀hire_date 用 DATE 取值直观JDBC 读取时对应 java.sql.Datesalary 用 DECIMAL(10,2)整数部分最大 99999999.99课设工资数据完全够用gender 用 CHAR(2) 是因为「男/女」正好占两个字符。外键 fk_emp_dept 在评审时是加分项它保证员工不能插入不存在的部门。导入后确认库里能看到三张以上的表tb_admin登录用、tb_dept部门、tb_employee员工。如果只看到一个空库大概率是脚本没执行完或者执行了但没有切到目标库。2.3 用 Navicat 还是命令行课设环境下我推荐的导入路径单纯导入脚本命令行和 Navicat 都能完成差别在排错效率。命令行 source 导入能看到每一条 SQL 的执行结果语法错误和字段类型不兼容会明确告诉你第几行有问题这是 Navicat 做不到的。我的建议是第一次用命令行 source确认脚本没问题之后再用 Navicat 运行 SQL 文件速度快。如果执行到一半报错先检查脚本里有没有多余的注释或者 MySQL 版本语法差异。MySQL 5.x 和 8.x 在这里就已经出现第一个差异8.x 默认认证方式是 caching_sha2_password老版本 JDBC 驱动连上来会被拒绝认证。这个坑在第 5 章会专门讲这里先记住一个原则驱动版本尽量和数据库版本对应不要拿 mysql-connector 5.1 硬连 MySQL 8.0。3. JDBC 连接与 DAO 层把增删改查写稳课设就过了一半3.1 驱动加载与连接参数mysql 5.x 和 8.x 之间的三个差异在人事管理系统里所有界面按钮最终都要落成 SQL 执行。而连接数据库这一步大多数人第一次跑不通都卡在这三个差异上。第一驱动类名。MySQL 5.x 用 com.mysql.jdbc.Driver8.x 改成了 com.mysql.cj.jdbc.Driver。第二URL 参数。8.x 必须带 serverTimezone否则报时区错误。第三SSL 与公钥。本地课设一般直接 useSSLfalse但 8.x 还可能遇到 Public Key Retrieval 问题对应解决方案在第 5 章。下面是这个资源里 DBHelper 工具类的常见写法import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBHelper { // MySQL 8.x 用 com.mysql.cj.jdbc.DriverMySQL 5.x 用 com.mysql.jdbc.Driver private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/hrm ?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; 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 main(String[] args) throws SQLException { try (Connection conn getConnection()) { System.out.println(连接成功 conn.getMetaData().getDatabaseProductName()); } } }代码逻辑说明Class.forName(DRIVER) 在类加载时向 DriverManager 注册驱动。虽然新版本 JDBC 驱动不写也能自动注册但保留这一行能让 5.x/8.x 之间切换更稳。getConnection() 每次调用都新建物理连接课设数据量小没有性能压力到第 6 章会把这个位置替换成连接池。参数说明localhost:3306/hrm 是 MySQL 地址、端口、库名库名必须和建库脚本里的 USE hrm 一致useSSLfalse 关闭 SSL 加密本地开发不需要serverTimezoneAsia/Shanghai 解决 8.x 时区报错characterEncodingutf8 配合表结构的 utf8mb4 保证中文不乱码。USER 和 PASSWORD 写你自己本机的账号不是资源自带的这是连接失败最高频的原因。写一个带 main 方法的测试类是最快的验证方式控制台输出「连接成功」以后再做 DAO 层。3.2 PreparedStatement 参数绑定为什么增删改都推荐它DAO 层代码在 src/dao 目录下负责员工新增、修改、删除、查询。用 Statement 拼接 SQL 虽然短但字符串里出现单引号会让 SQL 直接语法错误甚至造成 SQL 注入。PreparedStatement 在驱动层预编译参数用占位符 ? 传入既避免了拼接问题又挡住了注入。以新增员工为例public boolean addEmployee(Employee emp) { String sql INSERT INTO tb_employee(emp_no, emp_name, gender, dept_id, position, hire_date, salary, phone) VALUES(?,?,?,?,?,?,?,?); try (Connection conn DBHelper.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, emp.getEmpNo()); ps.setString(2, emp.getEmpName()); ps.setString(3, emp.getGender()); ps.setInt(4, emp.getDeptId()); ps.setString(5, emp.getPosition()); // 界面拿到的是 java.util.DateJDBC 需要 java.sql.Date ps.setDate(6, emp.getHireDate() ! null ? new java.sql.Date(emp.getHireDate().getTime()) : null); ps.setBigDecimal(7, emp.getSalary()); ps.setString(8, emp.getPhone()); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } }逻辑说明先写 SQL八个 ? 对应八个字段然后按下标顺序 set 值。setDate 值得单独说Swing 界面拿到的通常是 java.util.Date而 JDBC 只接受 java.sql.Date所以这里用 new java.sql.Date(emp.getHireDate().getTime()) 做转换如果 hireDate 为 null直接传 null 不会触发空指针。参数说明executeUpdate() 返回受影响行数插入成功返回 1所以返回 trueSQL 字段和表结构对不上会抛 SQLException打印堆栈后返回 false。try-with-resources 写法让 Connection、Statement 自动关闭不会留下连接泄漏。这段代码在整个课程设计里几乎可以复制到所有写操作上。3.3 员工列表查询ResultSet 到对象的映射习惯查询和更新不同执行 executeQuery() 拿到 ResultSet这是一个只能向前移动的行指针必须用 rs.next() 逐行遍历。常见的映射习惯是把数据库行转成 Employee 对象再放进 List界面层不直接接触 ResultSetpublic ListEmployee listEmployees() { String sql SELECT e.*, d.dept_name FROM tb_employee e LEFT JOIN tb_dept d ON e.dept_id d.dept_id ORDER BY e.emp_id; ListEmployee list new ArrayList(); try (Connection conn DBHelper.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Employee e new Employee(); e.setEmpId(rs.getInt(emp_id)); e.setEmpNo(rs.getString(emp_no)); e.setEmpName(rs.getString(emp_name)); e.setGender(rs.getString(gender)); e.setDeptName(rs.getString(dept_name)); e.setPosition(rs.getString(position)); e.setHireDate(rs.getDate(hire_date)); e.setSalary(rs.getBigDecimal(salary)); e.setPhone(rs.getString(phone)); list.add(e); } } catch (SQLException ex) { ex.printStackTrace(); } return list; }这段 SQL 用了 LEFT JOIN因为员工可能还没分配部门用 INNER JOIN 会把没部门的员工过滤掉列表数量对不上的时候很容易漏查这个原因。getDate(hire_date) 返回的是 java.sql.Date它是 java.util.Date 的子类所以 Employee 里用 java.util.Date 接收没有任何问题。getBigDecimal 对应数据库的 DECIMAL精确计算不会像 double 那样丢精度。到这里登录和员工管理背后需要的 JDBC 能力已经齐了连接、插入、查询。修改和删除是同一套写法把 SQL 换成 UPDATE、DELETE参数绑定顺序对应 WHERE 条件即可。下一步是回到 Swing 界面把这些方法挂到按钮上。4. Swing 界面与业务联动登录、表格、表单三条链路怎么串4.1 登录判断密码必须在后端校验人事管理系统的登录窗口是 JFrame用户名用 JTextField、密码用 JPasswordField。前端校验只能拦空值真正判断要看数据库里有没有这条管理员记录。loginButton.addActionListener(e - { String username usernameField.getText().trim(); String pwd new String(passwordField.getPassword()); if (username.isEmpty() || pwd.isEmpty()) { JOptionPane.showMessageDialog(loginFrame, 用户名和密码不能为空); return; } if (adminDao.checkLogin(username, pwd)) { loginFrame.dispose(); new MainFrame().setVisible(true); } else { JOptionPane.showMessageDialog(loginFrame, 用户名或密码错误请重试); } });adminDao 里的 checkLogin 方法关注两点。第一密码用 getPassword() 拿字符数组再转字符串而不是 getText()这是 Swing 的一个安全习惯避免密码以 String 形式常驻内存第二SQL 查询写成 SELECT COUNT(*) FROM tb_admin WHERE username? AND password?返回的 count 大于 0 就放行。这段代码里最容易被忽略的是 loginFrame.dispose()主窗口显示前先销毁登录窗口否则关掉登录窗口程序还留在后台答辩演示切窗口时会很尴尬。登录这块就这么短但它把界面、DAO、数据库三层全部串起来了。4.2 JTable 与 DefaultTableModel查询结果怎么进表格主窗口里的员工列表基本都用 JTable它本身不存数据数据放在 TableModel 里。DefaultTableModel 是最常用实现构造参数是列名数组和初始行数 0。DefaultTableModel model new DefaultTableModel( new Object[]{编号, 姓名, 性别, 部门, 职位, 入职日期, 工资, 电话}, 0); ListEmployee employees empDao.listEmployees(); for (Employee e : employees) { model.addRow(new Object[]{ e.getEmpNo(), e.getEmpName(), e.getGender(), e.getDeptName(), e.getPosition(), e.getHireDate(), e.getSalary(), e.getPhone() }); } empTable.setModel(model);参数说明DefaultTableModel 构造器的第二个参数 0 代表初始行数然后逐行 addRow第一个参数 Object[] 直接决定表格的列数量列位置和 addRow 数组顺序一一对应。工资列是 BigDecimal表格单元格默认显示不带两位小数可以重写 getColumnClass 或做格式化但课设标准下直接显示足够。列太窄会影响答辩观感建议顺手设置一下宽度和单选模式empTable.getColumnModel().getColumn(0).setPreferredWidth(80); empTable.getColumnModel().getColumn(1).setPreferredWidth(100); empTable.getColumnModel().getColumn(7).setPreferredWidth(120); empTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);刷新逻辑有一点血泪经验每次重新查询前先执行 model.setRowCount(0)否则上一次的数据还留在模型里新数据追加到尾部表格越刷越长看起来像重复数据。还有一点相关的坑如果表格上的数据需要点击排序可以调用 setAutoCreateRowSorter(true)但排序后 getSelectedRow 拿到的是视图行的索引取值前需要做 convertRowIndexToModel 转换不然删除时容易删错行。4.3 新增、修改、删除按钮的事件边界Swing 是事件驱动单线程模型按钮点击里直接调 DAO 方法就行不需要开子线程。删除场景要记住顺序先校验有没有选中行再弹确认框最后才执行删除。deleteButton.addActionListener(e - { int row empTable.getSelectedRow(); if (row 0) { JOptionPane.showMessageDialog(frame, 请先选中要删除的行); return; } String empNo model.getValueAt(row, 0).toString(); int confirm JOptionPane.showConfirmDialog(frame, 确认删除编号为 empNo 的员工, 删除确认, JOptionPane.YES_NO_OPTION); if (confirm JOptionPane.YES_OPTION empDao.deleteByEmpNo(empNo)) { model.setRowCount(0); loadData(); JOptionPane.showMessageDialog(frame, 删除成功); } });注意这里删除条件用的是 emp_no 而不是主键 emp_id。员工编号在表里有 UNIQUE 索引业务上用它定位更直观。修改同理UPDATE 语句的 WHERE 条件必须带主键或唯一键否则可能把全表的数据都改了——这个坑在课设答辩里被问到的概率不低。新增和修改通常弹一个 JDialog 表单把文本框内容读出来封装成 Employee 对象分别调 dao.addEmployee 和 dao.updateEmployee。一个容易忽略的小问题是日期输入框JTextField 读出来是字符串插入前必须按 yyyy-MM-dd 解析成 java.sql.Date否则 5.5 节那种 Incorrect date value 就会找上门。核心经验是界面只负责取值和提示数据库操作全部收敛在 DAO 层。这样后续做答辩演示时改界面、换数据库都比较从容。5. 部署与排查人事管理系统最常见的五个翻车现场这个资源自带的说明里提过它报的错误都是一些基础错误因为数据库版本不同造成的。下面这几条是我在部署同类 SwingJDBC 项目时见过最多的也是翻车概率最高的五个点。5.1 Public Key Retrieval is not allowed现象主程序第一次执行数据库查询时抛 SQLNonTransientConnectionException堆栈里明确写着 Public Key Retrieval is not allowed。原因MySQL 8.0 默认用 caching_sha2_password 做用户认证。客户端第一次连接时如果没有 SSL 加密服务端要求先获取 RSA 公钥用于密码加密而 JDBC 驱动出于安全考虑默认禁止自动获取公钥。解决在 URL 末尾加 allowPublicKeyRetrievaltrue。完整连接串变成 jdbc:mysql://localhost:3306/hrm?useSSLfalseallowPublicKeyRetrievaltrueserverTimezoneAsia/ShanghaicharacterEncodingutf8。如果还报同样的错把驱动 jar 换到 mysql-connector-java 8.0.16 以上早期版本对这个参数支持不完整。5.2 ClassNotFoundException: com.mysql.jdbc.Driver现象运行程序时控制台直接抛 ClassNotFoundException报错信息是 com.mysql.jdbc.Driver。原因驱动类名和 jar 版本不匹配。MySQL 8.x 的驱动类名已经改成 com.mysql.cj.jdbc.Driver代码里写的还是 5.x 的类名另一种情况是 jar 包根本没进 classpath编译器找不到。解决先确认 MySQL 版本。如果是 8.x把 DBHelper 里的 DRIVER 改成 com.mysql.cj.jdbc.Driver并在 lib 目录放 mysql-connector-java-8.0.x.jar如果是 5.x保留老驱动即可。jar 放进项目后一定要右键 Add to Build Path 或 Add as Library只拖进目录而不加构建路径编译器照样找不到这个问题在答辩前最容易临时爆出来。5.3 中文乱码现象员工姓名、部门名称在数据库和界面里显示成 ?? 或乱码。原因乱码是三层不一致导致的MySQL 连接 URL 没有指定字符集、建表字段不是 utf8mb4、SQL 脚本文件本身保存成 ANSI 编码。任何一层不对中文就会在导入或查询时变形。解决按顺序排查。先给 URL 加 characterEncodingutf8再确认建库语句里有 DEFAULT CHARACTER SET utf8mb4最后确认导入给 MySQL 的 SQL 脚本文件是用 UTF-8 保存的。做完这三点中文乱码基本不会出现。如果开发工具里界面乱码在启动参数 VM options 里加 -Dfile.encodingUTF-8 然后重启项目即可。5.4 开发工具里找不到 jar 包现象代码里 import java.sql.* 正常但 DriverManager 或 Class.forName 报红线运行时报 ClassNotFoundException。原因驱动 jar 没有正确加入项目构建路径或者用 Maven 自动下载依赖时因网络问题失败控制台出现 download from maven failed 这类提示。解决课设阶段建议直接绕开 Maven去 MySQL 官网或中央仓库下载对应版本的 mysql-connector-java.jar放进项目根目录下的 lib 文件夹然后右键 Build Path → Add to Build Path。IDEA 里选中 jar 后右键 Add as Library。如果坚持用 Maven把下载源切到阿里云镜像再刷新依赖。手工加 jar 虽然原始但解决「找不到类」这类问题的速度是最快的。5.5 日期和字段类型不匹配现象新增员工时 executeUpdate 抛 SQLException常见信息是 Incorrect date value 或 Data too long。有些错误更隐蔽插入成功但日期显示成 0000-00-00。原因两个点。界面传的日期是 java.util.Date 或字符串JDBC 需要 java.sql.Date不转换直接 setDate 会在类型转换阶段出错另外字段长度不够比如 VARCHAR(10) 存 11 位手机号或 DATE 字段收到了带时间格式的字符串。解决setDate 之前统一转成 java.sql.Date代码写法在 3.2 节已经给出。手机号、身份证这类字段在表设计阶段就放宽到 VARCHAR(30)避免数据处理时被截断。还有一个习惯从 JTextField 读日期字符串时先按 yyyy-MM-dd 做校验格式不对直接弹提示不让脏数据进 SQL。如果上面五条都没命中把堆栈里 SQLException 那行复制出来看提示。常见还有数据库端口 3306 被占用、密码错误导致 Access denied for user rootlocalhost、表名与 Java 代码里的 SQL 大小写不一致。其中表名大小写的问题在 Windows 开发机上不容易暴露因为 Windows 表名默认不区分大小写一旦部署到 Linux 或 macOS大小写不一致直接报 Table doesnt exist。我习惯在交项目之前用命令行执行一条 SELECT * FROM tb_employee 验证表名真实存在这一步能过滤掉很多隐藏问题。6. 进阶验证用数据库连接池替换 DriverManager 并做功能自测6.1 连接池改造Druid 替换 DriverManager 的最小改动课设代码跑通后如果想在答辩时加一个技术亮点我一般会建议把 DBHelper 里的 DriverManager 换成 Druid 连接池。改动量很小效果却很直观不用每次查询都重新建立物理连接员工列表刷新会快很多。先引入 druid-1.2.x.jar再参考下面的写法import com.alibaba.druid.pool.DruidDataSource; import java.sql.Connection; import java.sql.SQLException; public class DruidHelper { private static DruidDataSource dataSource; static { dataSource new DruidDataSource(); dataSource.setDriverClassName(com.mysql.cj.jdbc.Driver); dataSource.setUrl(jdbc:mysql://localhost:3306/hrm ?useSSLfalseserverTimezoneAsia/Shanghai); dataSource.setUsername(root); dataSource.setPassword(123456); dataSource.setInitialSize(3); dataSource.setMaxActive(10); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }关键参数initialSize3 表示启动时就建 3 个连接备用maxActive10 是最大连接数。课设并发量低这两个值已经足够。替换时把 DAO 里所有 DBHelper.getConnection() 改成 DruidHelper.getConnection() 就行DAO 层其他代码一行不用动。第一次跑容易踩 jar 包冲突确认 druid 和 mysql connector 两个 jar 都在构建路径里再运行。6.2 功能自测清单答辩前快速过一遍替换连接池之后我习惯在交作业前按下面的清单完整走一遍模块操作预期结果登录输入正确账号密码进入主窗体登录输入错误密码弹提示不崩溃员工管理新增一条员工记录表格立即刷新出现新行员工管理删除选中员工有确认框确认后行消失边界数据手机号输入 11 位数字正常保存不截断边界数据输入 or 11 查询结果为空不泄露数据这套流程我每次拿到新的课设资源都会强制走一遍因为它把连接、CRUD、边界处理全部覆盖到了。从那次在一台 MySQL 8 机器上被 Public Key 问题卡了两个小时之后我就养成了习惯拿到任何 SwingJDBC 项目先看数据库版本和驱动版本是否匹配再跑登录最后测一次 SQL 注入。希望这份人事管理系统的拆解能帮到你把踩坑时间省下来用到真正该用的地方。本文还有配套的精品资源点击获取
返回列表