Java Swing实现的SQL Server工资管理桌面程序(含完整源码与可运行class文件)

发布时间:2026/7/2 23:59:07
Java Swing实现的SQL Server工资管理桌面程序(含完整源码与可运行class文件) 本文还有配套的精品资源点击获取简介一个专为高校课程设计准备的工资管理桌面工具用Java Swing开发界面后端对接SQL Server数据库。支持员工信息全生命周期操作——添加、删除、修改、按姓名或工号精准查询部门信息维护薪资录入、调整与历史记录追踪多条件薪资查询按人、按部门、按工号密码修改与登录验证以及基础薪资分布统计分析。所有Java源文件均已编译生成.class字节码关键逻辑配有中文注释开箱即用。项目结构清晰类命名直观MainFrame是主窗口入口login处理身份校验AddEmployee/DeleteEmployee分别负责员工增删InquireOnName/InquireOnNo实现两种检索方式AnalyseSalary提供统计能力ConnectTest和DBConnect保障数据库连接稳定。适合教学演示、课程作业提交或作为二次开发起点。1. 项目概述为什么这个工资系统值得大学生花时间吃透你是不是正在为《Java程序设计》或《数据库原理与应用》的期末课程设计发愁老师布置了“做一个带数据库的桌面管理系统”但一打开IDEA就卡在登录界面怎么连SQL Server、员工列表怎么动态刷新、查询结果怎么塞进JTable里……别急这套Java Swing工资管理系统就是我当年带学生做实训时反复打磨出来的“教学锚点”——它不追求炫酷动画或微服务架构而是把高校课程设计最常踩的坑、最易失分的细节全摊开在你眼前。核心关键词“Java工资系统”“SQL Server实训”“Swing桌面应用”“高校课程设计”不是空泛标签而是每一行代码都在回应如何让一个零数据库经验的大三学生在两周内交出一份逻辑自洽、能跑通、能讲清楚、还能应付答辩提问的完整作品我试过让学生直接抄GitHub上那些“高大上”的Spring Boot工资系统结果90%的人卡在Maven依赖冲突、MyBatis配置报错、甚至Tomcat启动失败而用这个SwingSQL Server方案你只需要装好JDK 8/11、SQL Server Express免费版、SQL Server Management StudioSSMS再配好JDBC驱动双击Main.class就能看到登录框弹出来。它用最朴素的技术栈解决最实际的教学痛点界面交互是否直观数据库操作是否可追溯异常处理是否真实注释是否能让你看懂“为什么这里要先清空表格再填充数据”比如InquireOnName.java里那句tableModel.setRowCount(0);旁边注释写着“防止多次查询结果叠加显示”这比教科书上干巴巴的“清空表格模型”更戳中初学者的困惑。它不是一个成品软件而是一套“可拆解、可验证、可提问”的教学脚手架——你删掉一个类系统立刻报错你改一行SQL查询结果马上变化你断开数据库ConnectTest.java会明确告诉你“连接超时请检查SQL Server服务是否运行”。这种即时反馈才是课程设计该有的学习节奏。2. 整体架构与设计思路为什么选SwingSQL Server而不是其他组合2.1 技术选型背后的教学逻辑很多同学第一反应是“现在都2024年了还学Swing太老了吧”这话没错但放在高校课程设计场景下恰恰是它最大的优势。我们来算一笔账一个典型的课程设计周期是2~3周学生平均每天能投入的有效编码时间约2小时。如果选Web技术栈比如Spring Boot Vue光是环境搭建JDKMavenNode.jsVue CLI数据库驱动就要耗掉1.5天遇到“Thymeleaf模板找不到”或“跨域请求被拦截”查文档问群重装环境又得半天等页面终于跑起来发现后端返回的JSON格式不对还得回头调Controller层……整个过程像在迷宫里找出口而课程设计的核心目标——理解“数据如何从数据库经Java处理最终呈现到用户界面”——反而被层层抽象掩盖了。Swing则完全不同。它把“界面-逻辑-数据”三者牢牢焊死在同一进程里JButton点击触发ActionListenerActionListener里直接写JDBC查询查询结果ResultSet逐行读取后塞进DefaultTableModelDefaultTableModel绑定到JTable整个链条肉眼可见、调试器一步一跟。我在指导学生时会让ta在login.java的checkLogin()方法里打个断点输入账号密码后F8单步执行亲眼看着PreparedStatement.executeQuery()返回ResultSet再看着rs.next()循环把数据赋值给user对象——这种“所见即所得”的调试体验是任何Web框架都给不了的教学价值。SQL Server的选择同理相比MySQL它的图形化管理工具SSMS更符合国内高校机房的预装习惯相比SQLite它强制要求你理解“服务实例”“登录账户”“数据库权限”这些真实企业级概念而DBConnect.java里那句DriverManager.getConnection(jdbc:sqlserver://localhost:1433;databaseNameSalaryDB;usersa;password123456;)就是你第一次亲手拼接的生产级连接字符串里面每个参数的意义localhost:1433是默认端口databaseName指定库名user/password是SQL Server认证凭据都是答辩时老师最爱问的基础题。2.2 模块化设计如何让代码既清晰又防抄袭翻开源码目录你会发现命名极度“直男”AddEmployee.java、DeleteEmployee.java、InquireOnName.java……没有IEmployeeService或EmployeeControllerImpl这类让人头晕的接口实现类。这不是偷懒而是刻意为之的教学设计。高校课程设计最怕什么是学生从网上抄一套代码改个包名就交作业结果答辩时被问“InquireSalaryChange.java和InquireySalary.java有什么区别”当场哑火。这套系统的类命名本身就是一道防伪墙——InquireSalaryChange查的是薪资调整历史记录含旧薪资、新薪资、调整时间InquireySalary注意是y不是i查的是某月薪资明细工资条两个功能完全独立命名差异直指业务本质。你在AnalyseSalary.java里看到的饼图统计用的是JFreeChart库但代码只做了最基础的PieDataset填充和JPanel嵌入没封装成复杂图表组件——因为课程设计考察的是“能否用Java实现业务逻辑”而不是“会不会调第三方图表API”。模块间的依赖关系也刻意扁平化。所有数据库操作都通过DBConnect.java这个单例类统一管理它内部封装了连接池虽然只是简单的ArrayListConnection模拟但足够教学演示ConnectTest.java专门用来测试这个连接池是否健康。你看不到Spring的Autowired或Hibernate的SessionFactory所有Connection对象都是显式new DBConnect().getConnection()获取用完显式close()。这种“笨办法”强迫你理解资源释放的重要性——我见过太多学生在AddEmployee.java里忘了关PreparedStatement导致插入10条员工数据后第11条就报“连接数超限”这时候翻DBConnect.java里的getCount()方法立刻明白问题在哪。这种设计让代码不再是黑盒而是可触摸、可质疑、可修改的学习材料。2.3 安全与健壮性课程设计不该回避真实问题有些同学会疑惑“登录就用明文密码校验这也太不安全了吧”——这恰恰是本项目最硬核的教学点。login.java里的密码校验逻辑是String sql SELECT * FROM Users WHERE username? AND password?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, username); ps.setString(2, password); // 注意这里确实是明文但它旁边紧跟着一行注释“教学演示用实际项目需MD5/SHA256加密存储此处为简化流程”。这意味着什么意味着你在答辩时如果老师问“如何提升安全性”你可以自信地回答“我会在用户注册时用MessageDigest.getInstance(MD5).digest(password.getBytes())生成哈希值存库登录时对输入密码做同样哈希再比对同时增加盐值salt防止彩虹表攻击。”——这比背诵“应该用加密”有用一百倍。同样ChangePassword.java里有完整的密码二次确认逻辑两次输入必须一致MainFrame.java主窗口关闭时会弹出“确认退出”对话框这些细节不是炫技而是告诉你一个合格的桌面应用边界条件处理比核心功能更重要。我曾让学生故意在AddDepartment.java的部门名称输入框里敲入100个字符结果发现数据库字段dept_name VARCHAR(50)被截断这时ta才真正理解“为什么建表时要定义字段长度”而不是只在实验报告里抄一句“保证数据完整性”。3. 核心模块解析与实操要点从登录到统计每一步都在教你“怎么想”3.1 登录验证模块login.java不只是跳转更是状态管理的起点登录模块看似简单却是整个系统状态流转的枢纽。login.java继承自JFrame包含用户名密码输入框、登录按钮和“忘记密码”链接虽未实现但预留了JLabel占位。关键不在UI而在checkLogin()方法的三层校验逻辑第一层是前端空值校验if (username.trim().isEmpty() || password.trim().isEmpty()) { JOptionPane.showMessageDialog(this, 用户名或密码不能为空, 输入错误, JOptionPane.ERROR_MESSAGE); return; }这里trim()去首尾空格是很多学生忽略的细节——用户可能误按空格键导致“admin ”和“admin”被视为不同账号。第二层是数据库查询校验用PreparedStatement防止SQL注入哪怕教学场景也要种下安全意识的种子。第三层是登录成功后的状态传递它不直接new MainFrame().setVisible(true)而是通过this.dispose()关闭登录窗再new MainFrame(username).setVisible(true)将当前用户名传给主窗口。这个username参数在MainFrame.java里被存为private String currentUser;后续所有操作日志如薪资调整记录都会带上操作人信息这就是真实业务系统中“操作留痕”的雏形。提示调试登录失败时先运行ConnectTest.java确认数据库连通性再用SSMS手动执行SELECT * FROM Users WHERE usernameadmin检查表是否存在、数据是否正确最后在login.java的checkLogin()里加System.out.println(SQL执行前: sql);打印实际执行语句排除拼写错误。3.2 员工全生命周期管理Add/Delete/ChangeEmployee.javaCRUD背后的事务思维员工增删改是系统最频繁的操作也是最容易出错的模块。以AddEmployee.java为例它的核心不是“把数据插进数据库”而是如何保证数据一致性。比如添加新员工时需要同时向Employees表插入基本信息并向SalaryRecords表插入当月薪资记录。代码里没有用Transactional而是用最原始的JDBC事务控制conn.setAutoCommit(false); // 关闭自动提交 try { // 插入Employees String empSql INSERT INTO Employees (...) VALUES (...); ps1 conn.prepareStatement(empSql); // 插入SalaryRecords String salSql INSERT INTO SalaryRecords (...) VALUES (...); ps2 conn.prepareStatement(salSql); conn.commit(); // 两步都成功才提交 } catch (SQLException e) { conn.rollback(); // 任一步失败就回滚 JOptionPane.showMessageDialog(this, 添加失败 e.getMessage()); } finally { conn.setAutoCommit(true); // 恢复自动提交 }这段代码的价值远超“学会写INSERT语句”。它逼着你思考如果只插了员工没插薪资系统会出现“有员工没工资”的脏数据如果只插了薪资没插员工SalaryRecords.emp_id外键会指向不存在的员工ID违反参照完整性。DeleteEmployee.java同理删除前会先查询该员工是否有未发放薪资记录若有则弹窗提示“请先处理薪资再删除”而不是粗暴DELETE FROM Employees——这是在教你怎么用SQL的EXISTS子查询做业务前置校验。注意ChangeEmployee.java的修改逻辑有个精妙设计——它不是直接UPDATE Employees SET ... WHERE emp_id?而是先用SELECT * FROM Employees WHERE emp_id?查出原数据显示在修改窗体的文本框里用户改完再对比新旧值。只有当某个字段确实被修改了比如姓名从“张三”改成“张四”才生成对应的UPDATE语句。这样避免无意义的数据库写操作也方便后续做“修改日志”虽然当前版本没实现但代码结构已预留扩展点。3.3 多维度薪资查询InquireOnName/InquireOnNo/InquireDepartment.javaSQL能力的实战考场查询模块是检验你SQL功底的试金石。InquireOnName.java支持模糊查询SQL语句是SELECT e.emp_id, e.name, e.dept_id, d.dept_name, s.base_salary, s.bonus FROM Employees e JOIN Departments d ON e.dept_id d.dept_id JOIN SalaryRecords s ON e.emp_id s.emp_id WHERE e.name LIKE ?参数?传入的是%name%实现“张”能搜出“张三”“李张峰”。而InquireOnNo.java用的是精确匹配emp_id ?InquireDepartment.java则要关联三个表Employees、Departments、SalaryRecords并按部门分组统计平均薪资SELECT d.dept_name, COUNT(e.emp_id) as emp_count, AVG(s.base_salary) as avg_salary FROM Departments d LEFT JOIN Employees e ON d.dept_id e.dept_id LEFT JOIN SalaryRecords s ON e.emp_id s.emp_id GROUP BY d.dept_name这里用LEFT JOIN而非INNER JOIN是为了确保即使某部门暂无员工如新成立的“AI研发部”查询结果里依然会显示该部门emp_count为0——这是真实业务中常见的“保底展示”需求。我在指导学生时会让ta把InquireDepartment.java里的SQL复制到SSMS里手动执行观察结果集结构再对照Java代码里tableModel.addColumn(部门名称); tableModel.addColumn(员工数); tableModel.addColumn(平均薪资);的列定义理解“数据库字段”和“表格列”的映射关系。这种“数据库→Java→界面”的端到端追踪是课程设计最该掌握的能力。3.4 数据分析模块AnalyseSalary.java从数字到图表的思维跃迁AnalyseSalary.java用JFreeChart生成薪资分布饼图但重点不在绘图API而在数据准备逻辑。它不直接查SalaryRecords表而是先执行聚合SQLSELECT CASE WHEN base_salary 5000 THEN 5K以下 WHEN base_salary BETWEEN 5000 AND 10000 THEN 5K-10K ELSE 10K以上 END as salary_range, COUNT(*) as count FROM SalaryRecords GROUP BY CASE WHEN base_salary 5000 THEN 5K以下 WHEN base_salary BETWEEN 5000 AND 10000 THEN 5K-10K ELSE 10K以上 END这个SQL的精妙之处在于用CASE WHEN在数据库层完成分段统计而不是把几万条原始薪资数据全查出来再用Java循环判断分段——前者效率高后者内存爆。查询结果ResultSet被遍历后构建DefaultPieDatasetPieDataset dataset new DefaultPieDataset(); while (rs.next()) { dataset.setValue(rs.getString(salary_range), rs.getInt(count)); }然后ChartFactory.createPieChart(...)生成图表最后chartPanel new ChartPanel(chart);嵌入Swing容器。整个过程把“数据分析”拆解为“SQL聚合→Java数据结构转换→图表渲染”三步每一步都可调试、可替换。比如你想改成柱状图只需换createBarChart()想按部门分析就把SQL里的CASE WHEN换成d.dept_name分组。这种模块化思维比死记硬背JFreeChart的100个参数重要得多。4. 实操全流程从零开始运行、调试、二次开发的完整指南4.1 环境搭建三步到位拒绝“环境配置失败”第一步安装必备软件- JDK 8 或 11推荐OpenJDK 11官网下载后配置JAVA_HOME和PATH- SQL Server Express 2019微软官网免费下载安装时勾选“SQL Server和Windows身份验证模式”设置sa账户密码为123456- SQL Server Management StudioSSMS用于建库建表第二步创建数据库与表结构打开SSMS用sa账户登录新建查询执行以下SQL这是项目隐含的数据库契约必须严格遵循-- 创建数据库 CREATE DATABASE SalaryDB; GO USE SalaryDB; GO -- 创建部门表 CREATE TABLE Departments ( dept_id INT PRIMARY KEY IDENTITY(1,1), dept_name NVARCHAR(50) NOT NULL ); -- 创建员工表 CREATE TABLE Employees ( emp_id INT PRIMARY KEY IDENTITY(1,1), name NVARCHAR(50) NOT NULL, gender CHAR(2), birth_date DATE, dept_id INT, hire_date DATE, CONSTRAINT FK_Emp_Dept FOREIGN KEY (dept_id) REFERENCES Departments(dept_id) ); -- 创建薪资记录表 CREATE TABLE SalaryRecords ( record_id INT PRIMARY KEY IDENTITY(1,1), emp_id INT NOT NULL, month_year CHAR(7) NOT NULL, -- 格式2024-06 base_salary DECIMAL(10,2), bonus DECIMAL(10,2), total_salary AS (base_salary ISNULL(bonus, 0)), CONSTRAINT FK_Sal_Emp FOREIGN KEY (emp_id) REFERENCES Employees(emp_id) ); -- 创建用户表登录用 CREATE TABLE Users ( user_id INT PRIMARY KEY IDENTITY(1,1), username NVARCHAR(50) UNIQUE NOT NULL, password NVARCHAR(50) NOT NULL, role NVARCHAR(20) DEFAULT user -- admin or user ); -- 插入测试数据 INSERT INTO Departments (dept_name) VALUES (技术部), (销售部), (人事部); INSERT INTO Users (username, password, role) VALUES (admin, 123456, admin), (user1, 123456, user);提示执行完务必右键“SalaryDB”→“刷新”确认三张表已创建。如果报错“对象名’dbo.Departments’无效”说明没执行USE SalaryDB;。第三步配置JDBC驱动与运行- 下载mssql-jdbc-9.4.1.jre11.jar微软官方JDBC驱动适配JDK11- 将jar包放入项目根目录或在IDEA中Project Structure → Libraries添加- 双击Main.class或命令行java -cp .;mssql-jdbc-9.4.1.jre11.jar Main启动程序4.2 调试技巧快速定位90%的常见问题问题现象可能原因排查步骤解决方案启动报错ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriverJDBC驱动未加载检查DBConnect.java第1行Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver);是否执行确认jar包路径正确将mssql-jdbc-*.jar加入classpath或在IDEA中Run → Edit Configurations → VM options添加-cp .;path/to/jar登录时提示“连接数据库失败”SQL Server服务未启动或连接参数错误运行ConnectTest.java检查DBConnect.java中url字符串localhost:1433端口是否被占用databaseNameSalaryDB库名是否拼错在Windows服务里启动SQL Server (MSSQLSERVER)用SSMS连接localhost测试确保sa密码与代码中一致查询结果为空但数据库有数据SQL语句逻辑错误或参数未绑定在InquireOnName.java的executeQuery()前加System.out.println(执行SQL: sql , 参数: name);用SSMS执行相同SQL确认语法检查ps.setString(1, %name%)中name变量是否为空字符串添加员工后JTable不刷新表格模型未更新在AddEmployee.java的insert成功后检查是否调用了MainFrame.refreshEmployeeTable()或类似方法确保新增逻辑末尾有tableModel.addRow(new Object[]{...});或MainFrame.getInstance().refreshTable();实操心得我让学生养成“三查”习惯——查数据库SSMS里看数据是否真存在、查SQL把Java里拼的SQL复制到SSMS执行、查日志System.out.println()是Swing调试的最强武器。有一次学生InquireOnNo.java一直查不到数据最后发现是工号输入框里多了一个不可见的中文全角空格trim()后问题解决。这种细节只有亲手调试才能记住。4.3 二次开发入门三个安全又出彩的改造方向方向一增强登录安全性适合答辩加分项-目标将明文密码改为MD5哈希存储-步骤1. 修改login.java的checkLogin()String inputHash DigestUtils.md5Hex(password);需引入Apache Commons Codec库2. 修改Users表将password字段类型改为VARCHAR(32)3. 修改注册逻辑若项目有注册时存DigestUtils.md5Hex(inputPassword)-价值展示你理解密码安全的基本实践答辩时可延伸讨论“为什么不用SHA1”“盐值怎么加”。方向二导出Excel报表实用功能升级-目标在AnalyseSalary.java的饼图下方加“导出Excel”按钮-步骤1. 引入poi-ooxml-5.2.4.jarApache POI库2. 编写exportToExcel()方法创建XSSFWorkbook用ResultSet数据填充XSSFSheet3. 调用JFileChooser选择保存路径FileOutputStream写入文件-价值解决真实业务需求领导要看Excel报表且POI是Java领域最常用的Excel处理库学了不白学。方向三添加数据校验规则体现工程思维-目标在AddEmployee.java中对出生日期做逻辑校验不能大于今天不能小于1950年-步骤java try { LocalDate birth LocalDate.parse(birthText, DateTimeFormatter.ofPattern(yyyy-MM-dd)); if (birth.isAfter(LocalDate.now()) || birth.isBefore(LocalDate.of(1950, 1, 1))) { throw new IllegalArgumentException(出生日期不合理); } } catch (DateTimeParseException e) { JOptionPane.showMessageDialog(this, 日期格式错误应为yyyy-MM-dd); return; }-价值展示你考虑了用户输入的任意性比单纯“非空校验”更深入一层。5. 常见问题与避坑指南那些我没在代码里写的“血泪教训”5.1 数据库连接相关问题占调试时间的70%问题1“驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server建立安全连接”-原因新版SQL Server JDBC驱动默认启用SSL但本地Express版可能未配置证书-解决方案在DBConnect.java的连接URL末尾添加;encryptfalse;trustServerCertificatetrue即java String url jdbc:sqlserver://localhost:1433;databaseNameSalaryDB;usersa;password123456;encryptfalse;trustServerCertificatetrue;;问题2“登录失败用户‘sa’登录失败”-原因SQL Server默认禁用sa账户或密码错误-解决方案1. 打开SSMS用Windows身份验证登录2. 展开“安全性”→“登录名”→右键sa→“属性”3. 勾选“启用”在“状态”页确认“登录”设为“授予”4. 在“常规”页重置密码为123456问题3“数据库‘SalaryDB’不存在”-原因建库SQL执行失败或库名大小写敏感Linux服务器上-解决方案在SSMS中执行SELECT name FROM sys.databases;确认库名是否为SalaryDB注意大小写若为salarydb则修改DBConnect.java中的databaseName参数。5.2 Swing界面与事件处理陷阱问题1JTable点击无反应或双击编辑不生效-原因JTable默认不可编辑且未设置MouseListener-解决方案在MainFrame.java初始化表格后添加java table.addMouseListener(new MouseAdapter() { Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() 2) { // 双击 int row table.getSelectedRow(); if (row 0) { String empId table.getValueAt(row, 0).toString(); // 假设第一列是工号 new ChangeEmployee(empId).setVisible(true); // 弹出修改窗 } } } });问题2窗口关闭后程序未退出后台Java进程仍在运行-原因Swing默认关闭操作是HIDE_ON_CLOSE不是EXIT_ON_CLOSE-解决方案在MainFrame.java构造方法末尾添加java this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);同时在login.java登录成功后确保this.dispose()关闭登录窗否则两个JFrame共存会消耗资源。5.3 编译与运行时经典错误问题1“找不到或无法加载主类Main”-原因Main.java里public static void main(String[] args)方法签名错误或类路径未包含当前目录-解决方案检查Main.java是否为public class Main类名必须与文件名一致且main方法是public static void命令行运行时用java -cp .;mssql-jdbc.jar MainWindows或java -cp .:mssql-jdbc.jar MainMac/Linux。问题2“Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException”-原因在事件监听器中访问了尚未初始化的对象如JTable table为null-解决方案在MainFrame.java中确保所有组件JTable、JButton等在initComponents()方法里完成初始化且监听器代码在initComponents()之后注册。调试时在可疑行前加System.out.println(table table);确认是否为null。最后分享一个小技巧每次修改完代码不要急着运行先用IDEA的Analyze → Inspect Code扫描一遍。它会标出Resource leak: conn is never closed资源泄漏、Duplicated code重复代码等警告这些都是课程设计评分细则里明确扣分的点。我带的学生里凡是认真对待这些警告的答辩分数普遍高出10分以上——因为老师一眼就能看出这是个真正动手调试过、思考过代码质量的人。本文还有配套的精品资源点击获取简介一个专为高校课程设计准备的工资管理桌面工具用Java Swing开发界面后端对接SQL Server数据库。支持员工信息全生命周期操作——添加、删除、修改、按姓名或工号精准查询部门信息维护薪资录入、调整与历史记录追踪多条件薪资查询按人、按部门、按工号密码修改与登录验证以及基础薪资分布统计分析。所有Java源文件均已编译生成.class字节码关键逻辑配有中文注释开箱即用。项目结构清晰类命名直观MainFrame是主窗口入口login处理身份校验AddEmployee/DeleteEmployee分别负责员工增删InquireOnName/InquireOnNo实现两种检索方式AnalyseSalary提供统计能力ConnectTest和DBConnect保障数据库连接稳定。适合教学演示、课程作业提交或作为二次开发起点。本文还有配套的精品资源点击获取