尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

JavaSwing+MySQL+JDBC人事管理系统数据库课程设计实现详解

JavaSwing+MySQL+JDBC人事管理系统数据库课程设计实现详解 简介一份基于Java Swing MySQL JDBC的人事管理系统课程设计资源面向需要完成数据库课程设计或毕业设计的计算机专业学生也适合初学者学习桌面程序与数据库联动开发的完整思路帮助解决数据库设计、界面编码与系统整合等常见课程设计难点。资源包共24个文件内含12张系统运行界面截图、11个Java源文件与1个SQL数据库脚本压缩后仅143KB从目录上即可区分源码、截图与数据库脚本便于快速定位界面展示、业务逻辑与建表数据。已有3878人学习下载常用于人事管理类选题的参考与二次开发。通过源码能够掌握JDBC连接、登录验证、数据增删改查等核心实现SQL脚本便于在不同版本MySQL中导入调试界面截图可对照系统功能快速了解模块划分与操作流程。资源说明中提到的运行错误多由数据库版本差异引起属于可自行解决的基础问题适合有一定Java基础的学习者直接使用或改造。1. 数据库课程设计人事管理系统先搞懂这东西到底要交什么第一次做 javaswingmysqljdbc数据库 这套组合的人事管理系统时我花了一周写业务代码结果发现真正卡住我的不是 Swing 界面也不是增删改查的 SQL而是环境配置、驱动加载、时区和编码这些“看不见”的环节。等把这些坑踩完回头再看这个课题设计的核心其实只干三件事用 JavaSwing 画界面、用 JDBC 连 MySQL 8、用人事数据把数据库设计里的表、约束、事务串起来。这个方案能解决什么对正在做数据库课程设计的人来说它是一套能直接复现的骨架部门表、员工表、薪资表加登录权限标准的人事管理增删改查。对你动手能力的价值在于整套代码不依赖 MyBatis、不依赖 Spring所有连接和操作都走原生 JDBC数据库设计是否合理一眼就能看出来也最容易被答辩老师追问。适合谁适合数据库理论学完但没写过完整项目的人也适合想用最少的框架依赖把 Java 和 MySQL 打通的人。本文不贴完整源码但会把表结构、连接工具类、界面绑定和避坑点全部讲清楚照着写就能跑通。2. 先把 6 张表设计对人事系统的地基决定后面所有代码2.1 表结构设计业务表与编码表分开建人事管理系统不管界面多简单数据库表至少要覆盖真实人事管理的常见概念。很多课设只建一张员工表和一个用户表这样虽然能交但答辩时老师问“部门和员工的关系怎么体现”就答不上来。常见做法是分出 5 张业务表加 2 张辅助表。员工表t_employee是核心字段我建议这样设计emp_id 为主键自增emp_no 作为员工工号要带唯一约束因为真实系统里离职再入职不能重复编号emp_name 用 varchar(50)别用 charchar 会补空格导致查询对比时出错。dept_id 是外键指向部门表。入职日期 hire_date 用 date 类型薪资用 decimal(10,2) 而不是 floatfloat 算工资时会产生小数误差decimal 才能保证金额准确。部门表t_dept最简单dept_id 主键自增dept_name 唯一。这里有个容易忽略的点要给 manager_id 字段指向员工表的 emp_id表示部门负责人。如果员工表也存 dept_id部门和员工就形成了双向引用建表顺序必须注意——先建员工表会让外键报错因为部门表还不存在。所以建表顺序应该是t_user → t_dept → t_employee → t_salary先建被引用的表。薪资表t_salary单独拆出来而不是把工资字段放进员工表是因为一个员工可能有多次调薪记录。设计成 salary_id 主键、emp_id 外键、base_salary、bonus、deduction、pay_date 四个业务字段。这个拆分能体现你对第三范式的理解答辩时是很加分的点。登录用户表t_user不要和员工表合并因为课程设计的登录系统通常要区分管理员和普通员工两种角色user_id、username、password、role 四个字段就够了role 用 int 或 varchar 存建议用 varchar 存 admin 和 user可读性更好。password 字段记得用 varchar(64)以后如果要存 MD5 或 SHA-256 的散列值32 或 64 位长度都放得下。2.2 建表 SQL把约束和字符集一次写对直接在 MySQL 8 的客户端里执行下面这段建议用 navicat 或 mysql workbench 的查询窗口跑。字符集统一用 utf8mb4因为 mysql8 默认就是 utf8mb4它能存 emoji 和生僻字避免后面乱码排查。CREATE DATABASE hrms CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE hrms; CREATE TABLE t_user ( user_id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, role VARCHAR(20) DEFAULT user ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_dept ( dept_id INT PRIMARY KEY AUTO_INCREMENT, dept_name VARCHAR(50) NOT NULL UNIQUE, manager_id INT NULL, CONSTRAINT fk_dept_manager FOREIGN KEY (manager_id) REFERENCES t_employee(emp_id) ON DELETE SET NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;注意上面这段我没按顺序写t_dept 里引用了 t_employee实际执行时如果员工表还不存在外键会报错。正确做法是先把 t_employee 建好再建 t_dept或者在建表语句里暂时不写 manager_id 的外键等三个表都建完再用 ALTER TABLE 补上。课程设计里经常出现“创建表顺序混乱导致外键失败”的问题你在答辩时可以直接说“外键约束我放到最后统一加”这是很稳妥的做法。继续建员工表和薪资表CREATE TABLE t_employee ( emp_id INT PRIMARY KEY AUTO_INCREMENT, emp_no VARCHAR(20) NOT NULL UNIQUE, emp_name VARCHAR(50) NOT NULL, gender CHAR(2) DEFAULT 男, hire_date DATE, dept_id INT, phone VARCHAR(20), CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES t_dept(dept_id) ON DELETE SET NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_salary ( salary_id INT PRIMARY KEY AUTO_INCREMENT, emp_id INT NOT NULL, base_salary DECIMAL(10,2) DEFAULT 0.00, bonus DECIMAL(10,2) DEFAULT 0.00, deduction DECIMAL(10,2) DEFAULT 0.00, pay_date DATE, CONSTRAINT fk_salary_emp FOREIGN KEY (emp_id) REFERENCES t_employee(emp_id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里两个外键用了不同的删除策略值得记住t_employee 的 dept_id 删除部门时置空SET NULL因为一个部门解散了员工不能跟着消失t_salary 的 emp_id 删除员工时连带清掉薪资记录CASCADE因为员工都没了薪资记录没意义。这两个策略答辩老师最喜欢问答上来就说明你真的理解外键设计。给 t_dept 和 t_employee 补初始数据否则界面登录进去是空表看不出效果INSERT INTO t_user (username, password, role) VALUES (admin, 123456, admin); INSERT INTO t_dept (dept_id, dept_name) VALUES (1, 人事部); INSERT INTO t_dept (dept_id, dept_name) VALUES (2, 技术部); INSERT INTO t_employee (emp_no, emp_name, gender, hire_date, dept_id, phone) VALUES (E001, 张三, 男, 2023-06-01, 1, 13800001111);参数说明emp_no 是工号也是业务主键虽然 emp_id 已经自增但员工在 Excel 和工资单上显示的是工号所以加了 UNIQUE 约束。hire_date 用 DATE 而不是 DATETIME因为入职日期不需要时分秒。phone 用 VARCHAR 存很多新手用 INT 存手机号手机号超过 2^31 会溢出这是经典坑。3. 用 JDBC 连 MySQL 8驱动加载到 PreparedStatement 的封装3.1 先写连接工具类数据库连接池前的标准套路JDBC 的第一步是拿到数据库连接。建议单独建一个 JDBCUtil 类把连接信息放到 src 下的 db.properties 文件里不要硬编码在 Java 代码中。用 IDEA 开发时注意db.properties 要放在 src 目录下否则 CLASS_PATH 加载不到。先看 db.propertiesdrivercom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/hrms?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue usernameroot password123456说明一下 url 里这几个参数useSSLfalse 是因为本地开发不需要 SSL 加密mysql8 默认开 SSL 会报警告。serverTimezoneAsia/Shanghai 必须加不加会报时区错误 The server time zone value йʱ is unrecognized 或类似乱码提示。characterEncodingutf8 解决中文乱码。allowPublicKeyRetrievaltrue 在 mysql8 用 caching_sha2_password 插件时必须加否则会报 Public Key Retrieval is not allowed这是连接 MySQL 8 最常见的坑之一。再看连接工具类import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import java.io.InputStream; public class JDBCUtil { private static String driver; private static String url; private static String username; private static String password; static { try (InputStream in JDBCUtil.class.getClassLoader() .getResourceAsStream(db.properties)) { Properties props new Properties(); props.load(in); driver props.getProperty(driver); url props.getProperty(url); username props.getProperty(username); password props.getProperty(password); Class.forName(driver); // 加载驱动 } catch (Exception e) { e.printStackTrace(); throw new ExceptionInInitializerError(数据库配置加载失败); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } }逻辑说明静态代码块在类第一次加载时执行把 db.properties 里的配置读进内存然后 Class.forName 注册驱动。MySQL 8 以上用 com.mysql.cj.jdbc.DriverMySQL 5.x 用 com.mysql.jdbc.Driver两个驱动类名不一样混用会报 ClassNotFoundException。getConnection 每次调用返回一个新连接在课程设计这种单机低并发场景完全够用不需要一开始就上连接池。3.2 PreparedStatement、结果集与手动事务JDBC 增删改查的代码风格要统一否则界面层会越写越乱。下面是一个标准的按工号查询员工方法全程用 PreparedStatement 而不是 Statement可以防 SQL 注入也是答辩会被问到的点public static Employee findByNo(String empNo) { String sql SELECT emp_id, emp_no, emp_name, gender, hire_date, dept_id, phone FROM t_employee WHERE emp_no ?; Employee emp null; try (Connection conn JDBCUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, empNo); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { emp new Employee(); emp.setEmpId(rs.getInt(emp_id)); emp.setEmpNo(rs.getString(emp_no)); emp.setEmpName(rs.getString(emp_name)); emp.setGender(rs.getString(gender)); emp.setHireDate(rs.getDate(hire_date)); emp.setDeptId(rs.getInt(dept_id)); emp.setPhone(rs.getString(phone)); } } } catch (SQLException e) { e.printStackTrace(); } return emp; }代码里用了 try-with-resources 语法JDK7 以上支持这样 Connection、PreparedStatement、ResultSet 都能自动关闭不用手写 finally。这个写法本身就能规避“连接泄漏”问题课程设计的代码里如果出现手动 close 但忘了关 ResultSet 的情况运行久了会报 Too many connections。增删改的操作套路一样只是执行 executeUpdate 而不是 executeQuery。注意插入语句要返回自增主键时可以用 prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)执行后用 rs.getInt(1) 取出自增 id这个技巧在插入员工后要立刻登记薪资表时很实用。手动事务是课程设计要求里的重点通常给你一个场景“给员工调薪同时更新薪资表和个人状态”。这种跨表操作必须放在事务里下面这段是标准写法Connection conn null; try { conn JDBCUtil.getConnection(); conn.setAutoCommit(false); String sql1 UPDATE t_employee SET dept_id ? WHERE emp_id ?; String sql2 INSERT INTO t_salary (emp_id, base_salary, pay_date) VALUES (?, ?, NOW()); try (PreparedStatement ps1 conn.prepareStatement(sql1); PreparedStatement ps2 conn.prepareStatement(sql2)) { ps1.setInt(1, 2); // 调到技术部 ps1.setInt(2, 1); // 员工ID为1 ps1.executeUpdate(); ps2.setInt(1, 1); ps2.setBigDecimal(2, new BigDecimal(8500.00)); ps2.executeUpdate(); } conn.commit(); // 两个操作都成功才提交 } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }逻辑说明conn.setAutoCommit(false) 之后每条 SQL 不会自动提交必须等到 commit 才生效。中间如果第二条 SQL 失败会进 catch 分支执行 rollback第一条的修改也一起撤销。这里有三个参数是调的setInt 里面的目标部门ID和员工ID以及 setBigDecimal 里的薪资数。New BigDecimal(8500.00) 不要写成 8500.00 直接传 doubledouble 转 BigDecimal 会有精度损失。3.3 把 DAO 层从 Swing 界面层中剥离课程设计最常见的翻车写法是在 JButton 的 actionPerformed 里直接写 JDBC 代码。这样能跑但一个窗口几百行调试时无法定位到底是界面问题还是 SQL 问题。建议分层Swing 界面只调用 Service 或 DAO 方法不出现 Connection 和 PreparedStatement。我一般会按这个分包结构组织src/ db.properties com.hrms.util.JDBCUtil com.hrms.dao.EmployeeDao com.hrms.dao.SalaryDao com.hrms.model.Employee com.hrms.model.Salary com.hrms.ui.LoginFrame com.hrms.ui.MainFramemodel 里的 Employee 类是纯 JavaBean字段与 t_employee 一一对应ui 包下的类只做两件事收集用户输入、调用 DAO 返回结果展示。中间不需要 Service 层因为课程设计没有复杂业务规则DAO 直接暴露方法给界面即可。4. JavaSwing 界面层登录、员工管理与数据刷新4.1 登录窗口一个密码框的细节登录窗口看起来简单但有两个细节决定体验。第一密码框要用 JPasswordField 而不是 JTextField否则输入密码明文显示答辩现场很减分。第二登录按钮的 ActionListener 里要做空判断和角色判断不能只查 username 和 password 是否匹配。下面是一个最小登录逻辑JButton loginBtn new JButton(登录); loginBtn.addActionListener(e - { String name usernameField.getText().trim(); String pwd new String(passwordField.getPassword()).trim(); if (name.isEmpty() || pwd.isEmpty()) { JOptionPane.showMessageDialog(loginFrame, 用户名和密码不能为空); return; } User u UserDao.findByUsernameAndPassword(name, pwd); if (u ! null) { new MainFrame(u).setVisible(true); loginFrame.dispose(); } else { JOptionPane.showMessageDialog(loginFrame, 用户名或密码错误); } });注意 getPassword() 返回的是 char[] 而不是 Stringnew String 转一下是常规操作。登录成功后把 User 对象传给主窗口主窗口根据 role 判断是否显示“系统管理”菜单这是权限控制的简单实现。失败提示不要写“用户名不存在”或“密码错误”直接统一提示“用户名或密码错误”避免被猜到账户是否存在课程设计里也能体现安全意识。4.2 员工管理界面JTable 与刷新数据的正确姿势员工列表用 JTable 展示是主流做法。JTable 本身只负责显示数据放在 TableModel 里。每次查询后要刷新表格最简单粗暴也最可靠的方式是重新构建 DefaultTableModel再 setModel 到表格上。很多新手在同一个 TableModel 里改数据后调 fireTableDataChanged 发现界面不变原因在于 model 没被 JTable 引用或被引用了但结构已经变更。刷新表格的标准写法public void refreshTable(ListEmployee list) { String[] columns {工号, 姓名, 性别, 入职日期, 部门ID, 电话}; Object[][] data new Object[list.size()][columns.length]; for (int i 0; i list.size(); i) { Employee e list.get(i); data[i][0] e.getEmpNo(); data[i][1] e.getEmpName(); data[i][2] e.getGender(); data[i][3] e.getHireDate(); data[i][4] e.getDeptId(); data[i][5] e.getPhone(); } DefaultTableModel model new DefaultTableModel(data, columns); empTable.setModel(model); // 整体替换 model }逻辑说明每次刷新创建新 modelJTable 会重新绘制。这里有两个关键点第一是日期字段 hire_date 如果没有格式化表格里会显示成 “2023-06-01” 的字符串形式但如果你用 rs.getDate 得到 java.sql.Date 再放进 Object[]JTable 默认会显示成 “2023-06-01” 没问题但如果 getHireDate() 返回的是 java.util.Date显示出来是 “Thu Jun 01” 这种英文格式所以 DAO 层最好直接返回 java.sql.Date 或格式化好的字符串。第二是列宽工号和姓名的列宽不用改但电话列默认被压缩成省略号建议设置列宽empTable.getColumnModel().getColumn(5).setPreferredWidth(120)。删除员工时要先拿选中行的 emp_id这里有个坑表格显示的是工号 emp_no但删除 SQL 用 emp_id 作条件。正确做法是点击行时从 TableModel 里取工号再调用 EmployeeDao 按工号查 ID或者更省事把 emp_id 用 setUserObject 存在表格对象里但那个做法容易混淆课程设计用简单方案即可在 DAO 里直接提供 deleteByEmpNo 方法。4.3 ComboBox 显示部门名、提交部门ID下拉框的典型坑添加或编辑员工时部门选择用 JComboBox 展示所有部门。直观思路是“下拉框显示部门名选中某项提交时把这个名字存进员工表”但员工表的外键是 dept_id 不是 dept_name所以必须建立 显示值→真实值 的映射。常见做法是维护一个 List 下拉框里塞 dept_name选中后按下标从列表里取 dept_idprivate ListDept deptList; public void loadDeptData() { deptList DeptDao.listAll(); DefaultComboBoxModelString comboModel new DefaultComboBoxModel(); for (Dept d : deptList) { comboModel.addElement(d.getDeptName()); } deptComboBox.setModel(comboModel); } private int getSelectedDeptId() { int index deptComboBox.getSelectedIndex(); return deptList.get(index).getDeptId(); }getSelectedIndex 返回下拉框当前选中项的下标如果 deptList 和下拉框数据顺序一致这个取值就是准的。这里务必注意不要在加载下拉框后又对 comboModel 做 addElement 或 removeElement那会让列表和 deptList 顺序错位提交的 dept_id 就张冠李戴了。编辑员工时要在加载下拉框后定位到员工原来的部门for 循环遍历 deptList找到匹配的 dept_id再 setSelectedIndex(i)。5. 课程设计避坑环境、编码、表格刷新与事务处理的十次教训5.1 driver 找不到ClassNotFound 的三种情境现象运行程序第一行就抛 java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因最常见的是 mysql-connector-java 的 jar 包没有放进项目的构建路径。很多人在 IDEA 里下载了 jar 包但只加入了模块依赖没有复制到项目 lib 目录导致运行时类加载器找不到驱动类。第二种原因是 MySQL 版本和驱动版本不匹配比如 MySQL 8 却用了 5.1.x 的驱动连接时会直接报 “Unable to load authentication plugin caching_sha2_password” 或 ClassNotFound。解决用 IDEA 时打开 File → Project Structure → Modules → Dependencies把 mysql-connector-j 添加进去。另外在项目根目录建 lib 文件夹把 jar 复制进去再右键 Add as Library这种物理复制方式避免换机器后依赖丢失。如果版本不对去 MySQL 官网下载对应版本MySQL 8 用 connector/j 8.0.33 以上版本。5.2 中文乱码三种原因叠加现象写入数据库的中文变成问号或者界面上查出来的中文乱码。原因乱码不是单一代码问题而是三个环节的编码不统一。第一Java 源文件本身用了 UTF-8 编码但是 IDEA 全局默认是 GBK第二db.properties 里的 url 没有 characterEncodingutf8 参数第三数据库建库时字符集不是 utf8mb4。三个环节只要有一个断了中文就乱。解决在 IDEA 里 Settings → Editor → File Encodings 全部设成 UTF-8url 里加 characterEncodingutf8建库语句用 utf8mb4。排查时按这个顺序用 navicat 或 mysql workbench 依次检查能在哪一步看到乱码就说明断在哪一步。最隐蔽的是 IDEA 的 properties 文件默认用 ISO-8859-1 读取db.properties 里的中文乱码就是这个原因如果配置里没有中文则不受影响。5.3 时区问题MySQL 8 特有的拦路虎现象启动项目连接数据库时报错 Communications link failure后面跟着 “The server time zone value XXXXXXXX is unrecognized or represents more than one time zone”。原因MySQL 8 默认使用系统时区如果系统是 CST 这种缩写时区JDBC 驱动无法解析。这是 MySQL 8 比 MySQL 5.x 多出来的问题5.x 很少遇到。解决url 加 serverTimezoneAsia/Shanghai这个最省事。不要在 MySQL 端执行 set global time_zone08:00虽然也能解决但要重启服务端课设环境里没必要动服务器配置。5.4 程序卡死数据库连接被占用没释放现象界面点几次查询后程序越来越卡最后整个窗口假死控制台打印 “Too many connections”。原因打开连接但没有关闭。典型场景是在 finally 里只关了 PreparedStatement 没关 Connection或者用了 try-with-resources 但 Connection 是在 try 外面创建的导致连接泄漏。解决用 3.2 节展示的 try-with-resources 模式可以彻底根治。如果是自己手动关闭记住一个原则先关 ResultSet再关 Statement最后关 Connection顺序反了会导致 Statement 还持有 ResultSet 时被意外关闭。也可以用自建连接池接管但课程设计用 try-with-resources 就够了。设计工具类时还可以让 getConnection 每次返回新连接避免多个窗口共用同一连接导致一个窗口的事务阻塞另一个窗口的查询。5.5 JTable 死活不刷新重新 setModel 才是后悔药现象查询按钮点了控制台打出 SQL 查询结果但按钮上方的 JTable 内容不变。代码里用了 model.fireTableDataChanged() 也没用。原因fireTableDataChanged 只适用于原 TableModel 的数据行数没变、内容变了的情况。如果查询结果的行数变了比如第一次查出 10 条第二次查出 1 条原 DefaultTableModel 的行数没同步重构Swing 不会清掉多余的行。解决把表格模型整体替换也就是 4.2 节的 refreshTable 写法。每次重新 new DefaultTableModel(data, columns)然后 empTable.setModel(model)。这是最稳定、也最好向答辩老师解释的刷新方案。如果不想整体替换需要在原 model 上 setRowCount(0) 清掉所有行再逐行 addRow两个方案二选一不要混用。5.6 外键约束导致删除失败现象删除员工时报 mysqld_exception 或 SQLIntegrityConstraintViolationException提示 Cannot delete or update a parent row。原因t_salary 表里还有该员工的薪资记录外键约束阻止删除。如果在建表时用了 ON DELETE CASCADE则不会报错但很多课程设计里学生漏写了级联规则导致删不了数据。解决删除前先查 t_salary 表有没有该员工的记录有就先删工资记录再删员工。或者在建表时用 ON DELETE CASCADE 关联外键。推荐方案是界面层做二次确认弹窗提示“该员工有薪资记录删除后薪资记录也会一并删除”这比直接报红错误体验好很多。6. 让课设更像生产系统连接池、事务校验、自测清单6.1 引入一个轻量连接池为什么课程设计值得做这一步如果答辩老师问你“你的 JDBC 方案在生产环境有什么问题”答案就是每次 getConnection 都新建物理连接太慢。用连接池可以解决常见做法是引入 HikariCP它是目前 Java 生态里性能最好的连接池配置也比 DBCP 简单。只需要把 JDBCUtil 的获取连接方式改成从 HikariDataSource 拿private static HikariDataSource dataSource; static { HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/hrms?serverTimezoneAsia/ShanghaicharacterEncodingutf8); config.setUsername(root); config.setPassword(123456); config.setMaximumPoolSize(10); config.setMinimumIdle(2); config.setConnectionTimeout(3000); dataSource new HikariDataSource(config); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); }逻辑说明maximumPoolSize 设 10 意味着最多同时保持 10 个连接超过的请求排队等待。minimumIdle 设 2 是池里最少保持 2 个空闲连接避免刚启动时频繁创建。connectionTimeout 设 3000 毫秒如果 3 秒拿不到连接就抛异常而不是无限等下去这能防止死锁。注意引入了 HikariCP 之后try-with-resources 仍然适用conn.close() 的实际效果是归还连接到池中不是真的关闭。6.2 事务验证调薪操作必须成对生效事务部分最容易被忽略的是“验证”步骤。写完调薪功能后你要故意让第二条 SQL 报错确认第一条会不会被回滚。测试方法是在 ps2.executeUpdate() 之前手动写一行 int x 1 / 0; 制造运行时异常。运行后查询员工表如果部门没变说明回滚生效如果部门变了而薪资没插入说明你的事务没启作用多半是 setAutoCommit(false) 没被调起来或者连接对象在事务方法里被 Service 层 close 掉了。这个验证视角本质上是在验证“提交、回滚、关闭”三个动作的时序。回滚后连接要恢复 autoCommit 为 true 再还回连接池否则下一个使用该连接的请求会继续沿用 false 状态导致默默开启一个长事务。6.3 交付前的开放验证链路从界面到数据库的链路课程设计提交前我习惯跑三轮验证。第一轮是功能链路登录 → 添加员工 → 修改员工 → 删除员工 → 查询员工 → 调薪事务 → 退出每个按钮都点一遍记录操作结果。第二轮是数据落地验证停止程序后用 navicat 或 mysql workbench 连库直接查 t_employee 表确认界面操作的内容确实写到数据库里这一步能抓出“运行时不报错但数据根本没写进去”的隐藏 bug。第三轮是重启验证关闭程序重新启动看数据是否还保留。如果数据丢了检查是不是每次启动都执行了 DROP TABLE 或 CREATE TABLE有些课设为了方便测试把建表语句写在 main 方法里一启动就重建表数据全清空这是交付时最尴尬的事。最好再让程序支持一个“导出员工列表”到文本文件的功能不需要引入 POI 依赖用 BufferedWriter 写 CSV 格式就行。这不光是为了展示功能更是为了让答辩老师看到你考虑过数据落地。6.4 一个教训不要用 Thread.sleep(1000) 去等数据库连接曾经为了等数据库连接成功后弹提示在代码里写过 Thread.sleep(1000)。运行结果是在电脑通讯录里折腾了半天。数据库连接是同步的拿不到连接会直接抛异常或阻塞在 getConnection根本不需要 sleep。如果启动时连接失败显示一个明确的错误提示框比假装重试一整秒有意义得多。我的操作习惯是每写完一个功能就单独跑一次不把四个功能全写完再统一调试。比如写完登录就去测试连接、写员工列表就去查 SQL、写事务前就先跑一下回滚验证。这样出现问题能立刻定位到具体模块而不是在几百行代码里猜。这个顺序对只给两个月做课设的同学来说是最快拿到一个能跑通项目的路径。希望这一套 JavaSwing MySQL JDBC 的落地拆解能帮你在数据库课程设计里少一点玄学、多一点可控的确定性。本文还有配套的精品资源点击获取
返回列表