资讯动态

基于MySQL+Java+Swing的学生宿舍管理系统课程设计实战

发布时间:2026/10/27 2:08:52 来源:尧图企业网站定制
简介这份资源面向高校计算机相关专业学生与Java初学者提供一套可直接运行的MySQL课程设计项目——基于MySQL数据库、Java语言与Swing图形界面开发的学生宿舍管理系统适合用于课程设计选题、期末项目提交或数据库与桌面应用的综合练习。压缩包共334个文件约112.72MB以class编译文件与java源码为主体辅以png界面截图、xml配置、db数据库文件及jar依赖另含少量C工程残留文件整体结构完整、便于导入IDE后二次修改。项目围绕管理员管理、宿舍管理、学生信息管理、学生宿舍分配等模块展开源码中可见多个管理组件与接口类配合图表与文档可帮助读者理解数据库表设计、界面布局与业务逻辑的对应关系。目前已有268人学习下载适合需要一份可运行、可参考的MySQL课程设计范例的读者。1. 从一次答辩被追问说起这套宿舍管理系统到底要解决什么去年帮一个学弟看课程设计他做的是学生宿舍管理答辩时老师只问了一句「你这个系统宿管阿姨真的会用吗」他当场卡住。问题不在功能少而在他把系统做成了「数据库表的增删改查界面」没想过真实场景里谁在用、按什么顺序用。这套基于 MySQL Java Swing 的学生宿舍管理系统切入点就是把这个场景讲圆宿管要能快速查房、登记入住退宿辅导员要能按楼栋统计床位学生信息要能批量导入而不是一条条敲。它适合两类人——正在做 Java 课程设计、需要一套能跑通又能讲清楚设计思路的完整参考的学生以及想拿一个桌面端 CRUD 项目练手、把分层架构和数据库设计走一遍的入门开发者。整套东西的价值不在代码多花哨而在「需求—表结构—模块—验收」这条线是闭合的你照着改就能交。2. 需求与技术选型为什么是 Swing 而不是 Web2.1 先把三类使用者的动作拆出来做课程设计最容易翻车的地方是一上来就画界面。我一般会先拿一张纸把「谁、在什么情况下、做什么动作」列出来再决定要几张表、几个窗口。这个项目的使用者其实就三类动作也不复杂但每类人的关注点完全不同。角色核心动作关注点对应模块宿舍管理员登记入住、办理退宿、调换宿舍、查空床位操作快、少填字段、能看整栋楼状态住宿管理、床位管理辅导员/院系管理按楼栋/院系统计人数、导出名单数据准、能筛选、能导出统计报表、查询模块系统管理员维护楼栋房间、导入学生、管理账号批量操作、权限隔离基础数据、用户管理把这张表定下来后面所有设计都有依据。比如「宿管关注操作快」就决定了入住登记窗口不能有十几个必填项学生信息应该从已有档案里选而不是重新录入「辅导员要导出」就决定了查询结果必须支持导出成表格文件而不是只能看。很多同学的系统做完发现「功能都有但不好用」根子就在这一步没拆清楚直接照着数据库字段生成界面字段全但流程断。2.2 桌面端选型的真实理由网上课程设计一水儿的 Web 项目为什么这套选 Swing不是 Swing 更先进而是在课程设计的约束下它更「划算」。Web 方案要配 Tomcat、要写前端页面、要处理跨域和会话一个学生独立做完光环境搭建就能耗掉一周最后业务逻辑反而没时间打磨。Swing 是 JDK 自带的一个main方法就能跑起来答辩现场双击就能演示不用赌机房网络。对于「把数据库设计、分层架构、业务逻辑讲清楚」这个课程目标来说桌面端把复杂度压在了真正要考的地方。技术栈就三样都是课程里学过的Java SE 做业务和界面JDBC 连数据库MySQL 存数据。不引入 Spring、不引入 ORM 框架不是不会而是课程设计要展示「你自己会写 SQL、会管连接、会分层」套框架反而把该展示的东西藏起来了。这个取舍在答辩时是加分项老师问「为什么不用框架」你能答出「课程目标是掌握 JDBC 和分层思想框架会掩盖这部分实现」比含糊其辞强得多。2.3 环境与依赖的落地清单环境这块踩坑最多先把版本和依赖钉死能省掉一半「跑不起来」的问题。# 运行环境课程设计常用组合稳定优先 JDK 8 或 JDK 11 # Swing 在两者上都稳定别用太新的版本 MySQL 5.7 或 8.0 # 8.0 注意驱动包和时区配置 mysql-connector-java # JDBC 驱动版本与 MySQL 主版本对应 IDEIntelliJ IDEA 或 Eclipse驱动包要手动加到项目依赖里这是新手第一个卡点。MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver5.7 是com.mysql.jdbc.Driver写错了启动就报ClassNotFoundException。连接串里 8.0 必须带时区参数否则报时区错误// 数据库连接工具类核心片段 public class DBUtil { // 8.0 驱动类名带 cj5.7 不带这是最常见的翻车点 private static final String DRIVER com.mysql.cj.jdbc.Driver; // useSSLfalse 关掉 SSL 警告serverTimezone 解决 8.0 时区报错 private static final String URL jdbc:mysql://localhost:3306/dorm_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PWD 你的密码; static { try { Class.forName(DRIVER); // 静态块只加载一次驱动 } catch (ClassNotFoundException e) { throw new RuntimeException(驱动加载失败检查 jar 是否引入, e); } } public static Connection getConn() throws SQLException { return DriverManager.getConnection(URL, USER, PWD); } }这段代码看着简单但三个参数各有讲究characterEncodingutf8不写中文姓名入库变问号serverTimezone不写8.0 直接抛异常useSSLfalse不写控制台一堆警告干扰排查。我一般会把这个工具类单独放一个包所有 DAO 都从这里拿连接后面要换连接池也只改这一处。3. 总体设计四层结构与六张核心表的职责划分3.1 分层架构怎么切才不糊桌面项目最容易写成一锅粥——按钮的监听里直接写 SQL改一个字段要翻遍所有窗口。这套方案按经典四层切界面层Swing 窗口和面板、控制层处理按钮事件、校验输入、业务层封装入住退宿等业务规则、数据访问层DAO只管 SQL。切分的判断标准很简单界面层不出现Connection和SQLExceptionDAO 层不出现JFrame。只要守住这条线代码就不会烂。com.dorm ├── ui // 窗口、面板、表格模型 ├── controller // 事件监听、输入校验、调用 service ├── service // 业务规则床位是否占用、退宿结算 ├── dao // 增删改查纯 SQL ├── entity // 实体类与表字段对应 └── util // DBUtil、日期工具、导出工具这个包结构不是摆设。答辩时老师翻代码看到ui里干干净净只有界面逻辑dao里每个方法对应一条 SQL会认为你理解了分层反过来如果ui里出现PreparedStatement基本就暴露了「能跑就行」的心态。我带的项目里凡是分层守住的项目后期加功能都顺分层破了的加一个「调换宿舍」功能能改出三个 bug。3.2 六张核心表与字段设计表设计是这套系统的骨架字段不多但要经得起追问。核心是六张表学生表、楼栋表、房间表、床位表、住宿记录表、用户表。这里的关键设计决策是「床位单独成表」而不是在房间里存一个「已住人数」——因为要能查到具体哪个床位空着宿管安排入住时才有得选。-- 学生表档案信息与住宿记录分离一个学生可有多条历史住宿记录 CREATE TABLE student ( stu_id VARCHAR(20) PRIMARY KEY, -- 学号做主键业务唯一 name VARCHAR(30) NOT NULL, gender CHAR(1) NOT NULL, -- 男/女 college VARCHAR(50), -- 院系统计用 phone VARCHAR(20), status TINYINT DEFAULT 1 -- 1在校 0离校 ); -- 床位表核心设计一个床位一行占用状态直接查 CREATE TABLE bed ( bed_id INT AUTO_INCREMENT PRIMARY KEY, room_id INT NOT NULL, bed_no VARCHAR(10) NOT NULL, -- 如 1号床、2号床 is_occupied TINYINT DEFAULT 0, -- 0空 1占用入住退宿只改这个 FOREIGN KEY (room_id) REFERENCES room(room_id) ); -- 住宿记录表谁在什么时候住了哪个床位退宿写离宿时间 CREATE TABLE accommodation ( record_id INT AUTO_INCREMENT PRIMARY KEY, stu_id VARCHAR(20) NOT NULL, bed_id INT NOT NULL, check_in DATE NOT NULL, check_out DATE, -- 为空表示在住 FOREIGN KEY (stu_id) REFERENCES student(stu_id), FOREIGN KEY (bed_id) REFERENCES bed(bed_id) );床位表这个设计是整套系统的关键。很多同学图省事在房间表里放一个current_num字段记录已住人数结果要查「3 号楼还有哪些空床」时只能算出总数却不知道具体哪张床空着宿管没法安排。把床位拆成独立行is_occupied一查就清楚入住时把对应床位改成 1、退宿改回 0逻辑简单且不会出现「人数对不上床位」的脏数据。住宿记录表则保留了历史学生退宿后记录还在辅导员查「上学期谁住过这间」有据可查这也是答辩时容易被问到的点。3.3 业务规则放在哪一层分层定了还要想清楚「入住」这个动作到底做了什么。它不是简单往住宿记录插一行而是一个事务检查床位是否空闲、插入住宿记录、把床位标记为占用三步要么全成要么全败。这种规则必须放业务层不能散在界面里。// 业务层入住是一个事务三步必须一起成功 public boolean checkIn(String stuId, int bedId) { Connection conn null; try { conn DBUtil.getConn(); conn.setAutoCommit(false); // 关闭自动提交开启事务 // 1. 校验床位是否仍空闲防止并发或界面数据过期 if (!bedDao.isFree(conn, bedId)) { conn.rollback(); return false; } // 2. 插入住宿记录 accommodationDao.insert(conn, stuId, bedId, new Date()); // 3. 更新床位占用状态 bedDao.occupy(conn, bedId); conn.commit(); // 三步都成功才提交 return true; } catch (SQLException e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ex) { } return false; } finally { try { if (conn ! null) conn.setAutoCommit(true); } catch (SQLException ex) { } } }这段代码的重点不是语法而是「为什么要有事务」。如果只写插入和更新两条 SQL 而不开事务中间任何一步失败就会出现「记录有了但床位没占」或者「床位占了但没记录」的脏数据查房时对不上账。课程设计里能主动用事务并说清楚原因是很实在的加分点。参数上conn在 DAO 方法间传递是为了让多个操作共用同一个连接和事务这也是为什么 DAO 方法要设计成接收Connection而不是自己内部获取。4. 关键模块实现从登录到统计的落地细节4.1 登录与权限一个字段区分两种人登录模块看着简单但权限没做好后面全是漏洞。这套系统用用户表的一个role字段区分管理员和宿管登录成功后把角色存进会话对象主界面按角色决定显示哪些菜单。核心是「登录只做认证权限判断在进入功能前做」不要把权限判断塞进每个按钮的监听里。// 登录校验密码做 MD5 后再比对不存明文 public User login(String username, String password) { String sql SELECT * FROM sys_user WHERE username? AND password?; try (Connection conn DBUtil.getConn(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, MD5Util.encode(password)); // 入库前统一加密 ResultSet rs ps.executeQuery(); if (rs.next()) { User u new User(); u.setUserId(rs.getInt(user_id)); u.setRole(rs.getInt(role)); // 1管理员 2宿管 return u; } } catch (SQLException e) { e.printStackTrace(); } return null; // 返回 null 表示认证失败 }这里用PreparedStatement而不是字符串拼接是防 SQL 注入的基本功答辩时被问到「怎么防注入」能直接指这段。密码存 MD5 虽然不算强安全但课程设计层面能体现「不存明文」的意识比明文入库强。登录成功后主窗口根据role隐藏「用户管理」菜单宿管看不到账号维护入口这就是最朴素的权限隔离。4.2 入住退宿界面表格模型与数据联动Swing 里展示数据用JTable但新手常犯的错是把数据一条条addRow到表格里数据一多就卡而且和数据库对不上。正确做法是自定义TableModel让表格直接持有查询结果集转换后的列表界面刷新就是重新查一次数据。// 自定义表格模型列名固定数据来自 DAO 查询结果 public class BedTableModel extends AbstractTableModel { private final String[] cols {床位号, 房间, 状态, 在住学生}; private ListBedVO data new ArrayList(); public void reload(ListBedVO list) { this.data list; fireTableDataChanged(); // 通知表格整体刷新比逐行增删高效 } Override public int getRowCount() { return data.size(); } Override public int getColumnCount() { return cols.length; } Override public String getColumnName(int c) { return cols[c]; } Override public Object getValueAt(int r, int c) { BedVO b data.get(r); switch (c) { case 0: return b.getBedNo(); case 1: return b.getRoomNo(); case 2: return b.getOccupied() 1 ? 已占用 : 空闲; case 3: return b.getStuName() null ? - : b.getStuName(); default: return ; } } }用fireTableDataChanged()整体刷新而不是fireTableRowsInserted逐行通知是因为入住退宿后床位状态和学生在住信息会同时变整体刷新最省心。BedVO是个视图对象把床位、房间、学生三张表关联查询的结果拼在一起界面层不用再关心表关系。这个 VO 的设计是「界面要什么就查什么」一条关联 SQL 搞定避免界面里多次查库。4.3 统计与导出一条分组 SQL 解决辅导员的需求辅导员要的「按楼栋统计入住人数」本质是一条GROUP BY查询不需要在 Java 里循环累加。把统计逻辑压到 SQL 里既快又准还展示了你会写聚合查询。-- 按楼栋统计总床位、已占用、空余一条 SQL 出结果 SELECT b.building_name AS 楼栋, COUNT(bed.bed_id) AS 总床位, SUM(bed.is_occupied) AS 已占用, COUNT(bed.bed_id) - SUM(bed.is_occupied) AS 空余 FROM building b JOIN room r ON r.building_id b.building_id JOIN bed ON bed.room_id r.room_id GROUP BY b.building_id, b.building_name ORDER BY b.building_name;SUM(bed.is_occupied)这个写法利用了「占用为 1、空闲为 0」的设计求和就是占用数比COUNT(CASE WHEN...)简洁。查询结果直接喂给JTable展示导出时遍历表格模型写文件即可。导出功能建议用简单的 CSV 而不是 Excel 二进制格式CSV 用BufferedWriter逐行写不依赖第三方库课程设计里够用且不容易出兼容问题。导出路径让用户用JFileChooser选别写死到某个盘符换台机器就找不到文件。5. 避坑与排查五个最容易翻车的点5.1 中文乱码从建库到连接串要全链路一致现象是学生姓名入库变问号、界面显示方块。原因通常是三处编码不一致数据库建库没指定字符集、连接串没带characterEncoding、Swing 字体不支持中文。解决顺序是先查库SHOW CREATE DATABASE dorm_db;确认是utf8mb4再查连接串是否带characterEncodingutf8最后确认界面用的字体是「微软雅黑」这类中文字体而不是默认逻辑字体。三处对齐乱码基本消失。5.2 界面卡死耗时操作不能放在事件线程里现象是点「批量导入」后窗口白屏、按钮点不动。原因是 Swing 的事件处理都在事件分发线程EDT上跑导入几千条数据时主线程被占住界面自然不响应。解决办法是把耗时操作放到SwingWorker的doInBackground里执行完成后在done方法里刷新表格。这是 Swing 的经典坑答辩演示时如果导入卡死观感很差提前用SwingWorker包一层就能避免。5.3 连接泄漏每个 DAO 方法都要关资源现象是系统用一会儿就报「too many connections」。原因是Connection、PreparedStatement、ResultSet用完没关连接池或数据库连接数被耗尽。解决是用 try-with-resources 语法让资源自动关闭// try-with-resources 自动关闭顺序是 ResultSet - Statement - Connection try (Connection conn DBUtil.getConn(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { // 处理结果 } catch (SQLException e) { e.printStackTrace(); }注意事务场景下连接不能提前关要在finally里统一处理这也是为什么业务层的事务方法要手动管理连接生命周期。5.4 外键约束报错删除顺序和数据依赖现象是删学生时报「Cannot delete or update a parent row」。原因是住宿记录表还引用着这个学生。解决不是简单关掉外键检查而是按业务顺序处理先确认该学生没有在住记录check_out为空有就先办退宿再删档案或者设计成逻辑删除status置 0 而不物理删除。课程设计里推荐逻辑删除既避免外键冲突又保留历史数据答辩时还能讲「为什么不做物理删除」。5.5 演示环境翻车数据库没初始化现象是换台电脑演示程序连不上库或表不存在。原因是只拷了代码没带建库脚本。解决是把建表语句和数据初始化写成一个init.sql随项目一起交付演示前先执行一遍。我一般还会在DBUtil里加一个启动自检连不上库时弹窗提示「请先执行 init.sql 初始化数据库」而不是抛一堆堆栈让人懵。6. 验收与答辩怎么证明这套系统真的能用验收不是把功能点一遍就完事要按「场景走查 数据核对 代码抽查」三步来。场景走查选一条完整业务链新建楼栋房间 → 导入学生 → 办理入住 → 查空床位 → 办理退宿 → 看统计报表每一步都核对界面显示和数据库里的实际数据是否一致。数据核对重点看三个地方床位is_occupied和住宿记录check_out是否同步、统计数字和明细是否对得上、删除操作后关联数据是否处理干净。代码抽查让老师随机指一个功能你能从界面层一路讲到 DAO 的 SQL分层清晰就是最好的证明。答辩时高频问题集中在设计决策上提前准备好这几条的回答可能被问回答要点为什么床位单独建表要查具体空床位房间存人数只能得总数无法安排入住入住为什么用事务插记录和改床位状态必须同时成功否则数据对不上账为什么不用框架课程目标是掌握 JDBC 和分层框架会掩盖这部分实现并发入住同一床位怎么办入住前在事务内二次校验床位状态校验失败回滚密码为什么存 MD5不存明文是基本意识课程层面够用生产环境应加盐演示环节有个小技巧提前准备好一份「脏数据」场景比如故意留一个已退宿学生的记录现场演示查历史住宿证明系统不是只能处理干净数据。这比单纯点按钮有说服力。另外把init.sql和一键启动脚本放在项目根目录换机器演示前先跑一遍别赌现场环境。我带课程设计这些年最深的教训是功能做得再多讲不清「为什么这么设计」就白搭。从那以后我每次帮人看项目都强制让对方先用三分钟把「谁用、解决什么、关键设计取舍」讲一遍讲不顺的地方就是设计没想透的地方。这套宿舍管理系统的价值也在这里——它不大但每个模块背后都有能讲的理由。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑