ARTICLE DETAIL

资讯详情

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

Java Swing+SQL Server学生成绩管理系统实战指南

Java Swing+SQL Server学生成绩管理系统实战指南 简介本资源是一套面向计算机专业本科生的毕业设计实战项目基于Java Swing桌面框架与SQL Server数据库开发的学生成绩管理系统专为解决班主任日常成绩录入、统计、分析与报表打印等教学管理痛点而设计。压缩包共176个文件含31个核心Java源码、104个编译后class文件支撑完整MVC结构16个GIF图标与2个ICO资源保障界面美观性10个MP4讲解视频覆盖环境搭建、功能演示与关键逻辑解析另含SQL Server数据库文件mdf/ldf、项目配置文件及可直接运行的jar包整体容量183MB。目前已有187人学习下载资源结构清晰模块划分明确——如JF_view_*系列类对应学生、教师、成绩、查询等视图层JdbcAdapter封装数据访问配合系统设置与用户管理模块构成完整闭环。读者可直接部署运行、调试源码、理解Swing事件驱动机制并参考视频深入掌握Java GUI与数据库交互的工程实践细节。1. 为什么用 Java Swing SQL Server 做学生成绩管理系统现在还值得投入这不是一个“过时技术堆砌”的毕业设计——恰恰相反它是一块被低估的工程能力试金石。你可能在招聘网站上刷到“Java 开发岗要求熟悉 Swing 组件生命周期”“SQL Server 权限模型是企业级数据治理的起点”但很少有人告诉你一个能跑通增删改查、带事务回滚、支持多用户并发录入、字段校验不崩、导出 Excel 不乱码的 SwingSQL Server 成绩系统已经覆盖了 80% 中小教育信息化场景的真实交付边界。它不追求微服务架构或响应式前端而是逼你直面 JDBC 连接池泄漏、Swing EDT 线程阻塞、SQL Server nvarchar 与 varchar 混用导致的中文乱码、Windows 服务账户权限不足引发的数据库连接拒绝——这些不是“老古董问题”而是你在 Spring Boot 项目里调Transactional之前必须亲手拧紧的螺丝。适合两类人一是 Java 初学者需要一套可调试、可打断点、无黑盒框架干扰的完整闭环来建立数据流直觉二是转岗工程师想用最小技术栈验证自己对“客户端-服务端-数据库”三层协作的理解是否真实可靠。别被“Swing 已淘汰”的标签骗了——它仍是 Windows 教务终端最稳定、零依赖、免安装的 GUI 方案。2. 从零搭建环境JDK 8u291 SQL Server 2019 Express Swing 工程结构2.1 JDK 与 IDE 的版本锁定策略为什么必须用 JDK 8u291 而非 JDK 17Swing 在 JDK 9 引入模块化后部分 UI 类如javax.swing.plaf.nimbus.NimbusLookAndFeel被移入java.desktop模块而 SQL Server JDBC 驱动mssql-jdbc9.4 版本默认要求--add-modules java.se.ee才能加载javax.xml.bind这会导致 Swing 主窗体启动时抛NoClassDefFoundError: javax/xml/bind/annotation/XmlRootElement。血泪经验毕业答辩现场蓝屏只因导师电脑装了 JDK 17。解决方案是严格锁定 JDK 8u2912021 年最后一个长期支持版它自带完整javax.xml.bind且 Swing 渲染链路最稳定。验证命令java -version # 输出必须为java version 1.8.0_291提示不要用 OpenJDK 8某些发行版如 Amazon Corretto缺失jfxswt.jar会导致JFXPanel嵌入失败——这是后续做图表模块的伏笔先埋下。2.2 SQL Server 2019 Express 安装避坑三步法学生机常卡在“SQL Server 配置管理器打不开”或“数据库引擎服务启动失败”。根本原因不是安装包损坏而是 Windows 服务账户权限与 .NET Framework 版本冲突。按此顺序操作先装 .NET Framework 3.5含 2.0 SP2控制面板 → 程序和功能 → 启用或关闭 Windows 功能 → 勾选“.NET Framework 3.5包括 .NET 2.0 和 3.0”务必联网安装离线包易缺netfx3.cab以管理员身份运行安装程序右键SQLEXPR_x64_ENU.exe→ “以管理员身份运行”在“实例配置”页勾选“使用 Windows 身份验证模式”不要勾选“SQL Server Management Studio”SSMS 单独下载避免安装器卡死手动启动服务并验证端口net start | findstr MSSQL$SQLEXPRESS # 若无输出执行 sc config MSSQL$SQLEXPRESS start auto net start MSSQL$SQLEXPRESS # 检查 1433 端口是否监听 netstat -ano | findstr :1433若仍失败打开SQL Server 配置管理器→ SQL Server 网络配置 → SQLEXPRESS 的协议 → 启用TCP/IP→ 右键属性 → IP 地址页 → 将IPAll下的TCP Port设为1433删掉TCP Dynamic Ports的值。2.3 Eclipse 或 IntelliJ IDEA 工程结构src/main/java 与 lib 目录的物理意义Swing 项目不走 Maven 标准目录因为毕业设计需打包成单 jar 供答辩演示。工程根目录结构必须如下StudentScoreSystem/ ├── src/ # Java 源码非 Maven 结构 │ ├── main/ │ │ └── java/ │ │ └── com/example/score/ # 包名严禁用 default package │ │ ├── ui/ # Swing 界面类LoginFrame.java, MainFrame.java │ │ ├── dao/ # 数据访问类ScoreDao.java, StudentDao.java │ │ ├── model/ # 实体类Student.java, Score.java │ │ └── util/ # 工具类DBConnection.java, ExcelExporter.java │ └── resources/ # 数据库脚本与配置文件 │ ├── init_db.sql # 创建数据库、表、初始数据 │ └── db.properties # JDBC 连接参数 ├── lib/ # 第三方 jar必须 │ ├── mssql-jdbc-9.4.1.jre8.jar # 仅此版本兼容 JDK 8u291 │ └── poi-5.2.4.jar # Apache POI 导出 Excel └── README.md注意lib目录不是 Maven 的dependencies而是物理存放路径。Eclipse 中需右键项目 → Properties → Java Build Path → Libraries → Add JARs → 选择lib/下的 jarIntelliJ 中需 File → Project Structure → Modules → Dependencies → JARs or directories → 选中lib/文件夹。漏掉这步运行时必报ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver。3. 核心功能落地登录验证、成绩录入、Excel 导出的三段式代码实现3.1 登录模块Swing 表单 SQL Server 账号密码校验含防 SQL 注入Swing 登录界面不是简单JTextField拼接关键在事件驱动与线程安全。LoginFrame必须继承JFrame并实现ActionListener按钮点击触发actionPerformed()方法// LoginFrame.java public void actionPerformed(ActionEvent e) { if (login.equals(e.getActionCommand())) { String username usernameField.getText().trim(); String password new String(passwordField.getPassword()); // getPassword() 返回 char[]防内存泄露 if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(this, 用户名或密码不能为空, 输入错误, JOptionPane.WARNING_MESSAGE); return; } // 使用 PreparedStatement 防注入严禁 String.format(SELECT * FROM users WHERE name%s, username) String sql SELECT COUNT(*) FROM sys_user WHERE username ? AND password ?; try (Connection conn DBConnection.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, username); pstmt.setString(2, password); // 生产环境应加盐哈希此处简化 ResultSet rs pstmt.executeQuery(); rs.next(); if (rs.getInt(1) 0) { JOptionPane.showMessageDialog(this, 登录成功); this.dispose(); // 关闭登录窗 new MainFrame().setVisible(true); // 启动主界面 } else { JOptionPane.showMessageDialog(this, 用户名或密码错误, 登录失败, JOptionPane.ERROR_MESSAGE); } } catch (SQLException ex) { JOptionPane.showMessageDialog(this, 数据库连接失败 ex.getMessage(), 错误, JOptionPane.ERROR_MESSAGE); ex.printStackTrace(); } } }逻辑说明getPassword()返回char[]是 Swing 最佳实践避免String对象在内存中长期驻留明文密码PreparedStatement的?占位符由 JDBC 驱动自动转义比拼接 SQL 字符串安全百倍this.dispose()释放窗体资源否则多次登录会堆积多个JFrame实例。3.2 成绩录入模块JTable 编辑 批量插入 SQL Server含事务控制SwingJTable默认不可编辑需重写TableModel。但毕业设计更推荐直接绑定DefaultTableModel并设置列可编辑性// MainFrame.java 中初始化表格 DefaultTableModel tableModel new DefaultTableModel( new Object[]{学号, 姓名, 课程, 成绩, 录入时间}, 0) { Override public boolean isCellEditable(int row, int column) { return column 3; // 仅“成绩”列可编辑 } }; JTable scoreTable new JTable(tableModel); // 添加新行按钮逻辑 addBtn.addActionListener(e - { tableModel.addRow(new Object[]{null, null, 数学, 0, new Date()}); }); // 保存按钮批量插入开启事务 saveBtn.addActionListener(e - { Connection conn null; PreparedStatement pstmt null; try { conn DBConnection.getConnection(); conn.setAutoCommit(false); // 关闭自动提交 String sql INSERT INTO score (student_id, student_name, course, score, create_time) VALUES (?, ?, ?, ?, ?); pstmt conn.prepareStatement(sql); for (int i 0; i tableModel.getRowCount(); i) { pstmt.setString(1, (String) tableModel.getValueAt(i, 0)); pstmt.setString(2, (String) tableModel.getValueAt(i, 1)); pstmt.setString(3, (String) tableModel.getValueAt(i, 2)); pstmt.setDouble(4, (Double) tableModel.getValueAt(i, 3)); pstmt.setTimestamp(5, new Timestamp(((Date) tableModel.getValueAt(i, 4)).getTime())); pstmt.addBatch(); // 批量添加 } pstmt.executeBatch(); conn.commit(); // 提交事务 JOptionPane.showMessageDialog(this, 保存成功); } catch (SQLException ex) { try { if (conn ! null) conn.rollback(); // 回滚 } catch (SQLException rollbackEx) { rollbackEx.printStackTrace(); } JOptionPane.showMessageDialog(this, 保存失败 ex.getMessage()); ex.printStackTrace(); } finally { // 关闭资源实际项目应封装到工具类 try { if (pstmt ! null) pstmt.close(); } catch (SQLException ignored) {} try { if (conn ! null) conn.close(); } catch (SQLException ignored) {} } });参数说明setAutoCommit(false)是事务起点executeBatch()比循环executeUpdate()性能高 5~10 倍rollback()必须在catch块内显式调用否则连接池中的连接会处于未提交状态后续操作全卡死。3.3 Excel 导出模块Apache POI 处理中文与数字格式避坑字符集SQL Server 查询结果导出 Excel 最大陷阱是中文乱码与数字格式错乱。POI 4.1.2 版本默认用 UTF-8但 Excel 2003.xls格式需HSSFWorkbook而 2007.xlsx用XSSFWorkbook。毕业设计统一用.xlsx// ExcelExporter.java public static void exportToExcel(ListScore scores, String filePath) throws IOException { Workbook workbook new XSSFWorkbook(); // 用 XSSFWorkbook非 HSSFWorkbook Sheet sheet workbook.createSheet(成绩表); // 设置表头样式宋体、加粗、居中 Font headerFont workbook.createFont(); headerFont.setFontName(宋体); headerFont.setBold(true); CellStyle headerStyle workbook.createCellStyle(); headerStyle.setFont(headerFont); headerStyle.setAlignment(HorizontalAlignment.CENTER); // 写入表头 String[] headers {学号, 姓名, 课程, 成绩, 录入时间}; Row headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { Cell cell headerRow.createCell(i); cell.setCellValue(headers[i]); cell.setCellStyle(headerStyle); } // 写入数据行关键数字类型用 setCellValue(double)字符串用 setCellValue(String) int rowNum 1; for (Score score : scores) { Row row sheet.createRow(rowNum); row.createCell(0).setCellValue(score.getStudentId()); row.createCell(1).setCellValue(score.getStudentName()); row.createCell(2).setCellValue(score.getCourse()); row.createCell(3).setCellValue(score.getScore()); // double 类型自动识别为数值单元格 row.createCell(4).setCellValue(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(score.getCreateTime())); } // 自动列宽解决中文显示不全 for (int i 0; i headers.length; i) { sheet.autoSizeColumn(i); // 强制加宽避免中文被截断 sheet.setColumnWidth(i, sheet.getColumnWidth(i) 1024); } try (FileOutputStream fileOut new FileOutputStream(filePath)) { workbook.write(fileOut); } workbook.close(); }逻辑说明XSSFWorkbook比HSSFWorkbook更稳定支持中文setCellValue(double)让 Excel 识别为数值类型后续可求和、排序autoSizeColumn()后加1024是像素补偿因autoSizeColumn()对中文计算不准SimpleDateFormat格式化时间避免Date对象导出为 Excel 数字序列。4. 避坑指南Swing 线程阻塞、SQL Server 连接泄漏、中文乱码的 5 个真实翻车现场4.1 现象点击“查询成绩”按钮后界面假死鼠标变成沙漏10 秒后才刷新表格原因Swing 的事件分发线程EDT被耗时的数据库查询阻塞导致 UI 无法响应。常见误写new ScoreDao().queryAllScores()直接在actionPerformed()中调用。解决将查询逻辑放入SwingWorker后台执行并更新 UISwingWorkerListScore, Void worker new SwingWorkerListScore, Void() { Override protected ListScore doInBackground() throws Exception { return new ScoreDao().queryAllScores(); // 耗时操作在此执行 } Override protected void done() { try { ListScore scores get(); // 获取结果 updateTable(scores); // 在 EDT 中更新表格 } catch (Exception ex) { JOptionPane.showMessageDialog(MainFrame.this, 查询失败 ex.getMessage()); } } }; worker.execute(); // 启动后台任务4.2 现象连续操作 5 次后报错com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.原因DBConnection.getConnection()每次都新建连接但未在finally块中关闭导致连接数超限SQL Server Express 默认最大 32767 连接。解决必须用 try-with-resources 或显式 close且Connection、PreparedStatement、ResultSet三者都要关try (Connection conn DBConnection.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql); ResultSet rs pstmt.executeQuery()) { while (rs.next()) { /* 处理结果 */ } } // 自动关闭三者4.3 现象SQL Server 中存入的“张三”显示为“???”但用 SSMS 查看却是正常中文原因JDBC 连接 URL 缺少characterEncodingUTF-8参数且数据库创建时未指定Chinese_PRC_CI_AS排序规则。解决两步走——创建数据库时执行CREATE DATABASE student_score COLLATE Chinese_PRC_CI_AS;db.properties中 JDBC URL 改为jdbc.urljdbc:sqlserver://localhost:1433;databaseNamestudent_score;characterEncodingUTF-8;encryptfalse;trustServerCertificatetrue;4.4 现象导出 Excel 后“成绩”列显示为1.00E01而非10原因POI 默认将数字设为科学计数法格式未设置单元格样式。解决为成绩列单独设置数字格式CellStyle numberStyle workbook.createCellStyle(); numberStyle.setDataFormat(workbook.createDataFormat().getFormat(#,##0.00)); row.createCell(3).setCellValue(score.getScore()); row.getCell(3).setCellStyle(numberStyle);4.5 现象打包成 jar 后双击运行报错java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver原因mssql-jdbc-9.4.1.jre8.jar未打入最终 jar 包或 MANIFEST.MF 中Class-Path未正确指向lib/下的 jar。解决Eclipse 打包时选择 “Package required libraries into generated JAR”IntelliJ 选择 “Copy to output directory and link via manifest”手动检查 MANIFEST.MF 是否含Class-Path: lib/mssql-jdbc-9.4.1.jre8.jar lib/poi-5.2.4.jar5. 进阶技巧用 SQL Server 视图简化查询、Swing Tree 实现课程分类、动态报表生成5.1 用 SQL Server 视图替代复杂 JOIN 查询降低 DAO 层耦合度成绩表score、学生表student、课程表course三表关联查询在 DAO 层写死导致修改字段时要改 Java 代码。建视图将逻辑下沉至数据库-- 在 SQL Server 中执行 CREATE VIEW v_student_score AS SELECT s.student_id, s.student_name, c.course_name AS course, sc.score, sc.create_time FROM score sc JOIN student s ON sc.student_id s.student_id JOIN course c ON sc.course_id c.course_id;DAO 层查询语句简化为String sql SELECT * FROM v_student_score WHERE student_name LIKE ?; // 不再写 JOIN好处业务逻辑变更如增加班级字段只需改视图定义Java 代码零改动SQL Server 查询优化器对视图有更好执行计划。5.2 Swing JTree 实现课程树形导航带勾选框的课程筛选呼应热搜词“swing带勾选框的tree”Swing 默认JTree不支持复选框需自定义TreeCellRenderer和TreeSelectionModel。核心是继承DefaultTreeCellRenderer并重绘节点// CourseTreeCellRenderer.java public class CourseTreeCellRenderer extends DefaultTreeCellRenderer { private JCheckBox checkBox new JCheckBox(); Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); DefaultMutableTreeNode node (DefaultMutableTreeNode) value; String nodeName node.getUserObject().toString(); checkBox.setText(nodeName); checkBox.setSelected(node.isLeaf() isCourseSelected(nodeName)); // 叶子节点才可选 return checkBox; } private boolean isCourseSelected(String courseName) { // 从数据库读取已选课程列表返回 true/false return new CourseDao().isCourseSelected(courseName); } }注意JTree的setCellRenderer()必须在new JTree()后立即调用否则渲染无效勾选状态需维护在内存 List 中点击时更新checkBox.setSelected(!selected)并同步到数据库。5.3 动态报表生成用 SQL Server PIVOT 实现“学生成绩横向展示”传统成绩单是纵向每行一个成绩但教务处常需横向报表每行一个学生每列一门课。SQL ServerPIVOT一行搞定-- 动态生成列名因课程名不确定 DECLARE cols AS NVARCHAR(MAX), query AS NVARCHAR(MAX); SELECT cols STRING_AGG(QUOTENAME(course), ,) FROM (SELECT DISTINCT course FROM v_student_score) AS courses; SET query SELECT student_id, student_name, cols FROM (SELECT student_id, student_name, course, score FROM v_student_score) AS src PIVOT (MAX(score) FOR course IN ( cols )) AS pvt; EXEC sp_executesql query;Java 中用Statement.executeQuery()执行该动态 SQL结果集直接绑定到JTable无需 Java 层做行列转换。我带过 12 届毕业设计凡是把Swing EDT 线程、SQL Server 连接池、POI 中文编码这三座山翻过去的同学入职后写 Spring Boot 接口时debug 能力比同龄人快一倍——因为他们在 Swing 里亲手拧过每一颗螺丝知道Connection关不掉会怎样知道SwingUtilities.invokeLater()为什么存在知道Workbook关闭前不write()会丢数据。这套组合不是怀旧而是给你一个没有框架黑盒的沙盒让你看清数据从键盘敲下到硬盘落盘的每一毫秒。希望帮到你。本文还有配套的精品资源点击获取
返回列表