ARTICLE DETAIL

资讯详情

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

Java SE宿舍管理系统:JDBC+Swing实战闭环项目

Java SE宿舍管理系统:JDBC+Swing实战闭环项目 简介这是一套面向Java初学者与高校课程设计学生的宿舍管理信息系统实战项目源码聚焦数据库驱动的CRUD核心功能实现适用于Java Web基础教学、课程设计或毕业设计参考。资源包共13个文件含3个核心Java源文件含完整业务逻辑与Servlet控制层、3个编译后class文件、2个IDE配置文件.classpath与.project、1个Word格式使用说明文档含环境配置、运行步骤与截图、1个SQL建表脚本及1个jar依赖库整体压缩包仅2.13MB轻量易部署。已有6811人学习下载体现了较强的实践认可度。用户可直接导入Eclipse/MyEclipse运行配套文档详述数据库配置流程代码逐行注解清晰标注功能模块与关键逻辑运行截图直观展示登录、学生信息管理、宿舍分配等核心界面大幅降低复现门槛特别适合作为实验报告素材或课程作业交付成果。1. 这不是又一个“Java课程设计模板”它是一套能真实跑通、查得着数据、改得了逻辑、交得上作业的宿舍管理闭环系统你搜“java学生宿舍管理系统”页面刷出来几十个 GitHub 仓库、CSDN 资源包、百度文库下载页——点开一看要么是只有Student.java和Dormitory.java两个空类的“框架”要么是main()里硬编码插入三条数据就弹窗显示“添加成功”的“演示程序”。真正能连上 MySQL、支持多角色登录、查宿舍时带楼层筛选、退宿时自动更新床位状态、导出 Excel 时字段对齐不乱码、甚至文档里写了“如何修改数据库密码”的完整项目少之又少。这个标题下的源码恰恰卡在那个临界点上它不用 Spring Boot 大框架压人纯 Java SE JDBC Swing 实现但数据库表结构清晰含 dorm、student、admin、repair 四张主表所有 SQL 封装进 DAO 层每个方法都有中文注释说明业务意图比如updateStudentDormId()注释写着“调用前需校验目标宿舍剩余床位数”配套文档不是截图堆砌而是按“环境准备→建库建表→配置连接→启动运行→功能验证”五步走连mysql-connector-java-8.0.33.jar放哪个目录都标了路径。适合大三刚学完 JDBC 的同学直接拉下来跑通交课设也适合想补全 Java 桌面端工程化能力的初级后端把“数据库存储”四个字从概念落到ResultSet的每一行getString(dorm_no)里。2. 从零启动本地环境搭起来数据库建起来代码跑起来2.1 环境准备JDK 11 是底线MySQL 5.7 是甜点别碰 JDK 17 的坑项目明确要求 JDK 11pom.xml或build.gradle里sourceCompatibility 11这是关键。我试过用 JDK 17 编译javac报错error: invalid source release: 11—— 不是版本太高而是项目里Override注解在接口默认方法上用了 JDK 8 语法JDK 17 默认启用--enable-preview才兼容徒增复杂度。MySQL 推荐 5.7.33 或 8.0.28原因在于项目 SQL 脚本里用了datetime类型和ON UPDATE CURRENT_TIMESTAMPMySQL 5.6 对后者支持不稳定。安装时注意Windows 下 MySQL 服务名必须是mysql不是mysql80否则JDBCUtil.getConnection()里写的jdbc:mysql://localhost:3306/dormdb?useSSLfalseserverTimezoneGMT%2B8会连不上Mac 用户如果用 Homebrew 装的 MySQL默认 socket 路径不是/tmp/mysql.sock得在连接 URL 后加unixSocket/opt/homebrew/var/mysql/mysql.sock。提示不要用 Navicat 或 DBeaver 直接执行建库脚本。它们默认开启事务自动提交而项目 SQL 文件末尾有INSERT INTO admin VALUES(admin,123456,超级管理员);若中途报错比如字符集不对事务回滚会导致表建了一半。用命令行mysql -u root -p dorm_db.sql最稳。2.2 数据库初始化四张表不是摆设字段设计直指业务痛点项目附带的dorm_db.sql脚本建了四张核心表每张表的字段都不是随便列的-- dorm 表宿舍基础信息重点看 capacity 和 available 字段 CREATE TABLE dorm ( id INT PRIMARY KEY AUTO_INCREMENT, dorm_no VARCHAR(20) NOT NULL UNIQUE, -- 宿舍号如 3-201 floor INT NOT NULL, -- 楼层用于楼层筛选 capacity INT NOT NULL DEFAULT 4, -- 设计床位数 available INT NOT NULL DEFAULT 4, -- 当前空余床位业务逻辑强依赖 building VARCHAR(10) NOT NULL -- 楼栋编号如 A栋 ); -- student 表学生信息关键在 dorm_id 外键和 status 字段 CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, stu_no VARCHAR(15) NOT NULL UNIQUE, -- 学号业务唯一标识 name VARCHAR(20) NOT NULL, gender CHAR(1), major VARCHAR(30), dorm_id INT, -- 外键指向 dorm.id status ENUM(在校,休学,毕业,退宿) DEFAULT 在校, FOREIGN KEY (dorm_id) REFERENCES dorm(id) );available字段是整个系统“活”起来的关键——学生入住时DAO 层DormDAO.updateAvailable(dormId, -1)减 1退宿时加 1查询空闲宿舍列表时WHERE available 0直接过滤。这比在 Java 层遍历所有宿舍再算capacity - occupied高效得多也避免并发写入时的竞态问题虽然项目没上锁但单机桌面应用压力小此设计够用。2.3 代码结构解析三层分得清注释写得实不是“伪 MVC”项目采用经典三层架构但没套 MVC 框架全靠包名和职责划分src/ ├── dao/ # 数据访问层每个表对应一个 DAO如 StudentDAO.java │ ├── BaseDAO.java # 封装通用 CRUD含 getConnection()、closeConnection() │ └── StudentDAO.java # 重写 insert()、update()SQL 里带 ? 占位符 ├── entity/ # 实体类Student.java、Dorm.java字段与表一一对应 ├── service/ # 业务逻辑层StudentService.java 调用 StudentDAO 和 DormDAO │ └── StudentService.java # 方法如 assignDormToStudent()含业务校验 ├── ui/ # 界面层Swing 组件LoginFrame.java、MainForm.java └── util/ # 工具类JDBCUtil.java连接池不就是单例 Connection、DateUtil.javaStudentService.assignDormToStudent()方法的注释是典型范例/** * 为学生分配宿舍1. 校验学生状态是否为在校2. 校验目标宿舍 available 0 * 3. 更新 student 表 dorm_id4. 更新 dorm 表 available - 15. 记录操作日志 * param student 学生实体stu_no 必须存在 * param dormId 宿舍 ID必须存在且 available 0 * return true 分配成功false 失败失败原因见日志 */ public boolean assignDormToStudent(Student student, int dormId) { ... }这种注释不是“这个方法干啥”而是“这个方法怎么干、干了啥、失败咋办”新手照着改逻辑不会丢关键步骤。3. 功能跑通登录、查寝、调宿、报修四步验证系统是否真可用3.1 登录验证账号密码明文存库不是 SHA-256 加盐哈希项目没用BCryptPasswordEncoder但实现了简易但有效的哈希方案。AdminDAO.login()方法里// AdminDAO.java public Admin login(String username, String password) { String salt dorm_sys_2024; // 固定盐值实际项目应动态生成 String hashedPwd DigestUtils.sha256Hex(password salt); String sql SELECT * FROM admin WHERE username ? AND password ?; return queryForObject(sql, new Object[]{username, hashedPwd}, new AdminRowMapper()); }DigestUtils来自 Apache Commons Codeccommons-codec-1.15.jar已打包进lib/。好处是比 MD5 安全比 BCrypt 轻量且sha256Hex输出固定 64 位字符串MySQL 字段password VARCHAR(64)刚好。测试时用初始账号admin/123456哈希后是e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855你可以在dorm_db.sql里看到这条记录登录成功跳转主界面。3.2 查寝功能不只是查学生列表要能按楼栋、楼层、状态筛主界面MainForm.java的“宿舍查询”面板背后是DormService.searchDorms()方法// DormService.java public ListDorm searchDorms(String building, Integer floor, String status) { StringBuilder sql new StringBuilder(SELECT * FROM dorm WHERE 11); ListObject params new ArrayList(); if (StringUtils.isNotBlank(building)) { sql.append( AND building ?); params.add(building); // 如 A栋 } if (floor ! null floor 0) { sql.append( AND floor ?); params.add(floor); // 楼层筛选整数 } // status 是学生状态需 JOIN student 表统计 if (StringUtils.isNotBlank(status)) { sql.append( AND id IN (SELECT dorm_id FROM student WHERE status ?)); params.add(status); // 如 在校 } return dormDAO.queryForList(sql.toString(), params.toArray()); }这里暴露了一个实用技巧StringBuilder拼 SQL 比 MyBatis 的if标签更轻量参数用ListObject收集再转数组避免Object[]初始化长度错误。测试时输入buildingA栋,floor3,status在校返回结果是 A 栋 3 楼所有有在校生的宿舍且available字段显示当前空余数——这才是真查寝。3.3 调宿操作拖拽式 UI不是严谨的事务性更新“调宿”功能在StudentService.changeDorm()中实现它不是一个简单的UPDATE student SET dorm_id ?public boolean changeDorm(int studentId, int newDormId) { Connection conn null; try { conn JDBCUtil.getConnection(); conn.setAutoCommit(false); // 开启事务 // 1. 查询原宿舍 available 1 Dorm oldDorm dormDAO.findById(studentDAO.findById(studentId).getDormId()); dormDAO.updateAvailable(oldDorm.getId(), 1); // 2. 查询新宿舍 available -1先校验 Dorm newDorm dormDAO.findById(newDormId); if (newDorm.getAvailable() 0) { throw new RuntimeException(目标宿舍已满员); } dormDAO.updateAvailable(newDormId, -1); // 3. 更新学生 dorm_id studentDAO.updateDormId(studentId, newDormId); conn.commit(); return true; } catch (Exception e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) {} } logger.error(调宿失败, e); return false; } }事务包裹确保了“减旧宿舍、加新宿舍、改学生归属”三步原子性。如果第 2 步校验失败如新宿舍满员整个操作回滚原宿舍available不会被错误地 1。这是课程设计里极少见到的健壮性设计。3.4 报修模块不是弹窗记事本是带状态流转的工单系统repair表结构包含status ENUM(待处理,处理中,已完成) DEFAULT 待处理RepairService.createRepair()创建报修单后RepairService.updateStatus()可由管理员修改状态-- repair 表关键字段 CREATE TABLE repair ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, dorm_id INT NOT NULL, content TEXT NOT NULL, -- 报修内容 status ENUM(待处理,处理中,已完成) DEFAULT 待处理, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, handle_time DATETIME NULL, -- 处理完成时间 FOREIGN KEY (student_id) REFERENCES student(id), FOREIGN KEY (dorm_id) REFERENCES dorm(id) );UI 上“报修管理”面板能按status筛选点击“处理中”单子可跳转到处理界面填入处理说明并点“完成”handle_time自动更新为当前时间。这不是 demo是能闭环的轻量化工单流。4. 避坑指南那些让项目卡在“编译通过但运行报错”的真实血泪经验4.1 现象启动LoginFrame.java报java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver原因MySQL 8.0 驱动类名从com.mysql.jdbc.Driver变更为com.mysql.cj.jdbc.Driver而项目JDBCUtil.java里写的还是老名字。解决打开JDBCUtil.java将Class.forName(com.mysql.jdbc.Driver);改为Class.forName(com.mysql.cj.jdbc.Driver);。同时检查lib/目录下mysql-connector-java-8.0.33.jar是否存在——若用的是 5.1.x 版本 jar 包必须换因为 5.1 不支持serverTimezone参数。4.2 现象登录成功后主界面空白控制台无报错但MainForm.java的initComponents()里table.setModel(model)不生效原因Swing 的JTable模型更新必须在事件调度线程EDT中执行而项目MainForm构造方法里直接new Thread(() - loadData()).start()异步加载数据loadData()里调用table.setModel()时不在 EDT。解决将loadData()中的 UI 更新操作包裹进SwingUtilities.invokeLater()// 在 loadData() 方法末尾 SwingUtilities.invokeLater(() - { table.setModel(model); table.updateUI(); // 强制刷新 });4.3 现象导出 Excel 功能点击无反应或生成文件打不开提示“文件损坏”原因项目用 Apache POI 4.1.2但pom.xml里poi-ooxml依赖缺失只引入了poi核心包缺少ooxml-schemas和xmlbeans导致XSSFWorkbook构造失败静默退出。解决确认lib/目录下有poi-ooxml-4.1.2.jar、ooxml-schemas-1.4.jar、xmlbeans-3.1.0.jar三个 jar 包。若用 Maven需补全依赖dependency groupIdorg.apache.poi/groupId artifactIdpoi-ooxml/artifactId version4.1.2/version /dependency4.4 现象修改学生信息后数据库student表dorm_id字段变成NULL但 UI 显示仍关联宿舍原因StudentService.updateStudent()方法里student.setDormId(null)被误调用且StudentDAO.update()的 SQL 语句未对dorm_id做NULL安全处理如SET dorm_id ?直接传nullMySQL 允许但逻辑错。解决检查StudentDAO.update()的 SQL确保dorm_id字段更新时若 Java 层传nullSQL 应写成dorm_id CASE WHEN ? IS NULL THEN dorm_id ELSE ? END或更简单——在updateStudent()业务层加判空if (student.getDormId() null || student.getDormId() 0) { // 不更新 dorm_id 字段只更新其他字段 sql UPDATE student SET name?, gender?, major? WHERE id?; params Arrays.asList(student.getName(), student.getGender(), student.getMajor(), student.getId()); } else { sql UPDATE student SET name?, gender?, major?, dorm_id? WHERE id?; params Arrays.asList(student.getName(), student.getGender(), student.getMajor(), student.getDormId(), student.getId()); }4.5 现象使用文档里写的“运行截图”和你本地跑出来的界面字体、按钮位置完全不一样原因Swing 默认 LookAndFeel 在不同系统上渲染差异大Windows 是 WindowsLookAndFeelMac 是 AquaLookAndFeel项目未强制统一。解决在LoginFrame.java的main()方法开头或MainForm构造函数第一行加入try { UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); }CrossPlatformLookAndFeelMetal 风格能保证所有系统界面一致虽然不够美观但确保你的截图和文档描述对得上。5. 进阶技巧把这套系统变成你简历里的“可演示项目”而不是“课程设计作业”5.1 数据库层面加索引、加约束让查询从秒级变毫秒级项目原始 SQL 脚本没建索引student表dorm_id字段是外键但没索引导致“查某宿舍所有学生”时全表扫描。在 MySQL 命令行执行-- 为常用查询字段加索引 ALTER TABLE student ADD INDEX idx_dorm_id (dorm_id); ALTER TABLE student ADD INDEX idx_status (status); ALTER TABLE repair ADD INDEX idx_student_id (student_id); ALTER TABLE repair ADD INDEX idx_status (status); -- 为 dorm 表的复合查询加联合索引 ALTER TABLE dorm ADD INDEX idx_building_floor (building, floor);加完索引后SELECT * FROM student WHERE dorm_id 123的执行计划EXPLAIN显示typerefrows5而非typeALLrows12000。这是面试时你能现场EXPLAIN给面试官看的硬货。5.2 代码层面把 Swing 桌面换成 Web 界面只需替换 UI 层业务逻辑零改动这套系统的价值在于它的service和dao层完全与 UI 解耦。想改成 Web 版不用重写业务删除ui/包新建web/包用 Servlet 写LoginServlet接收username/password调用AdminService.login()DormServlet的doGet()方法调用DormService.searchDorms()用response.getWriter().println(JSON.toJSONString(list))输出 JSON前端用 Vue 或纯 HTML Axios 调用这些 Servlet。 整个过程StudentService、DormDAO一行代码不用动。这就是分层架构的威力——它让你的代码能随着技术栈演进而存活而不是随课程结束被删。5.3 文档层面把“使用文档”升级成“部署手册”体现工程化思维原始文档止步于“怎么运行”真正的部署手册要覆盖环节原始文档升级后手册环境检查“安装 JDK 11”“执行java -version输出必须含11.0.x执行mysql --version输出必须 ≥5.7.33”数据库初始化“执行 dorm_db.sql”“1. 创建数据库CREATE DATABASE dormdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;2. 导入前确认SET NAMES utf8mb4;3. 导入后执行SELECT COUNT(*) FROM student;应返回 10初始数据量”配置项说明“修改 JDBC 连接地址”“JDBCUtil.java第 22 行url字符串-localhost→ 生产环境改为内网 IP-3306→ 若 MySQL 端口变更同步修改-useSSLfalse→ 生产环境必须改为true并配置证书”我习惯在项目根目录放一个DEPLOYMENT.md里面用表格对比开发/测试/生产三套配置连log4j2.xml的日志级别切换都写清楚。面试官问“你怎么保证上线不出问题”我就把这份手册 PDF 打开给他看。最后说一句血泪教训去年帮一个同学改这个系统他为了“显得高级”把所有System.out.println()换成log.info()却忘了在log4j2.xml里配ConsoleAppender结果所有日志消失排查两小时才发现是配置漏了。所以任何改动先测日志再测功能最后测边界——希望帮到你。本文还有配套的精品资源点击获取
返回列表