我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

基于SQL Server与Swing的宾馆管理系统开发实践

基于SQL Server与Swing的宾馆管理系统开发实践 简介这是一份基于SQL Server和Java Swing实现的宾馆管理系统课程设计成品适合数据库或Java方向需要完整项目参考的高校学生。整套资源共40个文件包含Java源代码、编译后的class字节码、可直接运行的Jar程序、SQL建库脚本、数据库物理文件以及使用说明文档压缩包仅2.02MB架构轻量且便于部署。项目使用Swing构建客户端界面结合miglayout布局库完成界面布局SQL脚本与数据库物理文件配套齐全同时保留了可直接运行的Jar包读者可对照源码和文档快速搭建环境既能用于验收讲解也便于在此基础上扩展功能。目前已有377人学习下载对于正在完成数据库或Java课程设计的同学来说是一份值得参考的实战样例。1. 项目背景与整体设计思路宾馆管理系统属于典型的管理信息系统MIS开发场景几乎每个计算机相关专业的学生或者刚入行的开发人员都会在某个阶段接触到类似的题目。用SQL Server搭配Swing来做这套系统可以说是一个非常经典的组合Swing负责桌面端界面展示和交互SQL Server负责数据持久化与业务规则约束两者通过JDBC桥接起来。这个系统要解决的核心问题是宾馆前台日常运营中最繁琐的那几件事客人来了要快速登记入住客人走了要准确计算房费退房结账期间还要处理预订、换房、续住、查询历史记录等操作。如果全靠纸笔或Excel数据混乱、对账困难是必然的。而用一套桌面的管理系统配合数据库的约束和事务能力就能把前台业务理顺账目也能对得上。这套项目适合谁如果你正在做课程设计、毕业设计或者想通过一个完整项目把Java SE、JDBC、SQL Server这些知识点串起来练手那这个题目的价值非常高。它麻雀虽小五脏俱全界面、数据库、业务逻辑、异常处理全都涉及做完之后你会对“一个软件从数据库到界面到底是怎么跑通的”有非常具体的体感。我把整个项目拆成四个层次来做数据库层负责表结构、约束、存储过程数据访问层用JDBC封装所有增删改查业务层处理入住、退房这类流程性操作界面层用Swing展示房态、表单和账单。这个分层看着简单但每层职责一旦清晰后续调试和扩展都会省很多力气。1.1 为什么选SQL Server Swing这个组合先说实话如果只图省事用SQLite或者Access配个简单的图形界面也能做出来。但SQL Server的价值在于它提供了完整的约束机制、事务隔离、并发控制这些特性在“入住登记”和“账单结算”这种需要保证数据一致的场景里非常关键。Swing则是Java自带的标准桌面GUI框架不需要额外安装运行环境打包成JAR后在一台装了JDK的Windows机器上就能跑对于宾馆前台的部署场景非常友好。有人会问为什么不选MySQLMySQL也可以但SQL Server的图形化管理工具SSMSSQL Server Management Studio对新手更友好建表、设计索引、查看执行计划都有可视化界面调试SQL语句特别直观。而且SQL Server的语法和类型系统在某些场景下更严格比如decimal类型做金额计算、datetime2做时间存储能帮你从一开始就养成规范的数据库设计习惯。还有一个很实际的原因是学校机房和企业里最常见的数据库就是SQL Server无论以后做运维还是做开发这套技能都有复用价值。1.2 系统功能模块怎么拆功能模块的划分决定了代码结构我会把系统拆成六个主要模块客房管理房型维护单人间、双人间、套房、房价设置、房间状态管理空闲、已订、入住、维修客户管理登记客人基本信息姓名、身份证号、电话支持会员信息记录预订管理客人提前预订房间记录预订日期、入住日期、预订天数入住登记将空闲房间分配给客人生成入住记录记录预收款退房结账根据入住时长和房价计算费用支持现金、银行卡多种支付方式生成账单查询统计按时间段查询入住率、营业收入按房型统计出租率每个模块对应一个数据表或多个数据表界面上的一个Tab页或一个菜单项。刚开始做的时候最容易犯的错是把所有功能堆在一个窗体里后面代码越改越乱所以要提前规划好。2. 数据库设计SQL Server落地的关键细节数据库是整个系统的地基。很多同学上来就建表一边写代码一边改表结构结果到后期逻辑全乱。正确做法是先想清楚业务流程涉及哪些实体、实体之间有什么关系再动手建库建表。2.1 sql server下载安装与建库环境准备在做数据库设计之前先把环境准备好。SQL Server的版本选择上本机开发可以用SQL Server 2008 R2或SQL Server 2012这两个版本的安装包体积小对内存要求低学习完全够用如果机器配置较高直接用SQL Server 2022开发版或Express版也行。Express版是免费且轻量的适合部署到宾馆前台那种配置不高的电脑上。安装的时候要注意几点实例名默认是MSSQLSERVER密码模式下要选择“混合模式SQL Server身份验证和Windows身份验证”并设置sa密码这样才能用JDBC通过账号密码连接数据库。装完后一定要安装SQL Server Management StudioSSMS管理工具是必须的。SQL Server在启动后会占用一定内存这是正常的Windows NT服务进程的内存占用可以通过“最大服务器内存”选项来限制比如设成512MB避免前台电脑卡顿。装好之后在SSMS里新建数据库我习惯命名为HotelDB。排序规则用默认的Chinese_PRC_CI_AS这样中文检索和排序才正常。建库SQL很简单CREATE DATABASE HotelDB ON PRIMARY ( NAME NHotelDB, FILENAME NC:\SQLData\HotelDB.mdf, SIZE 10MB, FILEGROWTH 10% ) LOG ON ( NAME NHotelDB_log, FILENAME NC:\SQLData\HotelDB_log.ldf, SIZE 5MB, FILEGROWTH 10% );2.2 核心表结构设计与约束使用宾馆管理系统核心表一般有六张Room客房表、RoomType房型表、Guest客人表、Reservation预订表、CheckIn入住表、Bill账单表。下面给出关键字段设计思路。RoomType表房型ID作为主键房型名称、门市价、押金金额。房价用decimal(10,2)而不是float因为浮点数在金额计算上会有精度误差这是SQL Server开发里很常见的一个坑。Room表房间号作为主键房型ID作为外键关联RoomType表房间状态字段用tinyint存储0空闲、1已订、2入住、3维修这个状态字段会被Swing界面的房态图直接引用。CheckIn表要重点说明入住ID为主键房间号、客人ID、入住时间、预计离店时间、实际离店时间、预收款、操作员。房间号在这里要冗余存储一份方便查询某房间的历史入住记录不要只依赖外键关联。表建好后外键约束和检查约束要加完整。比如房型表的主键被房间表引用就不能随意删除有房间记录的房型Bill表的付款金额必须大于0用CHECK约束保证入住时间不能晚于离店时间也用一个约束卡住。数据库层做一层保护应用层做一层判断双重保险。2.3 视图与存储过程的实际应用除了基础表我还会建几个视图和存储过程来简化Java端代码。比如实时房态视图RoomStatusView把Room表、RoomType表、CheckIn表关联起来直接展示每个房间当前状态、房价、入住客人姓名。Java端查询这个视图一次就能拿到房态列表的所有数据省去多次关联查询和手工拼接的麻烦。存储过程方面退房结账StoreProcedure是典型的应用场景。整个退房流程要完成三件事计算总费用、生成账单记录、把房间状态改为空闲。这三步必须在一个事务里完成否则会出现费用算了但房间没释放或者房间释放了但账单没生成的情况。用存储过程封装数据库端直接保证事务Java端只需要调用一次。CREATE PROCEDURE usp_CheckOut checkInId INT, paymentMethod INT, operator VARCHAR(50), billId INT OUTPUT AS BEGIN SET NOCOUNT ON; DECLARE totalAmount DECIMAL(10,2), roomId INT, deposit DECIMAL(10,2); BEGIN TRANSACTION; SELECT totalAmount DATEDIFF(HOUR, ci.CheckInTime, GETDATE()) / 24.0 * rt.Price, roomId ci.RoomId, deposit ci.Deposit FROM CheckIn ci INNER JOIN Room r ON ci.RoomId r.RoomId INNER JOIN RoomType rt ON r.RoomTypeId rt.RoomTypeId WHERE ci.CheckInId checkInId AND ci.ActualCheckOutTime IS NULL; IF totalAmount IS NULL BEGIN ROLLBACK TRANSACTION; RETURN -1; END INSERT INTO Bill (CheckInId, TotalAmount, PaymentMethod, Operator, BillTime) VALUES (checkInId, totalAmount, paymentMethod, operator, GETDATE()); SET billId SCOPE_IDENTITY(); UPDATE Room SET Status 0 WHERE RoomId roomId; UPDATE CheckIn SET ActualCheckOutTime GETDATE() WHERE CheckInId checkInId; COMMIT TRANSACTION; END这个存储过程把计算、记账、改状态集中在一起事务回滚机制保证了任何一步失败都不会留下脏数据。3. 整体开发环境与工具选型工欲善其事必先利其器。整个项目的开发环境建议统一好版本避免踩环境不兼容的坑。我这次使用的组合是JDK 1.8 SQL Server 2012 SQL Server Management Studio 18 Eclipse或IDEA。Swing是JDK自带的不需要额外引入依赖。JDBC驱动选用sqljdbc4.jar这个JAR包从SQL Server 2008到2019都能兼容把JAR放到项目的lib目录下并添加到Build Path即可。除了基础IDE建议额外安装两个辅助工具一是DBeaver或Navicat用于日常查看SQL Server数据方便快速检查表数据是否正确二是用JFormDesigner或WindowBuilder插件做Swing界面的可视化拖拽布局虽然Swing手写布局也不难但有可视化工具能省下一半时间。如果你更想深入掌握布局原理手写代码更好BorderLayout、GridLayout、GridBagLayout这几种布局结合着用就足够应付这个项目了。4. Swing界面设计与核心功能实现Swing做界面难的不是控件使用而是布局和交互逻辑的组织。宾馆管理系统界面比较典型有菜单栏、工具栏、状态栏以及中央的房态图和工作区。4.1 主窗体结构与布局技巧主窗体我用JFrame作为基类默认大小1280x800居中显示关闭时自动释放资源。整体布局采用BorderLayout北侧放工具栏中央放带有TabbedPane的工作区南侧放状态栏西侧可选地放一个导航面板。工具栏里放常用功能的快捷按钮入住登记、退房结账、房间查询、客户管理。按钮用ImageIcon加载小图标文字加在旁边鼠标悬停时显示提示文本。状态栏用一个JLabel实时显示当前操作员、当前时间、房间数统计实现方式是Swing的Timer事件每秒刷新一次。房态图的实现是这个界面的亮点。我建议用GridLayout铺一个房间网格每个房间用一个自定义的JButton显示房间号按钮背景色代表状态绿色为空闲、红色为入住、黄色为已订、灰色为维修。点击按钮弹出该房间的详情和操作菜单这个方法比表格显示直观得多前台人员扫一眼就能掌握全局。4.2 入住登记与退房结账的界面流程入住登记界面的数据布局要按操作员习惯排列先选房型再选房间号然后填客人信息最后填写预收款和入住天数。房型下拉框用JComboBox房间号用JComboBox联动刷新当房型变化时自动查询该房型下空闲的房间。客人身份证号是必填项需要校验格式从身份证中解析出生日期和性别自动填入对应文本框。退房结账界面是另一个重点。输入或选择入住记录后表格列出该客人的入住天数、房型门市价、应付金额、预收款和找零金额。这里计算逻辑用BigDecimal做不要用doubleSwing里展示时可以精确到小数点后两位。确认结账后调用2.3节的存储过程传入入住ID和支付方式返回账单ID后弹出结账成功提示并打印小票信息到文本域。4.3 功能菜单的价值另外一个容易被忽视的点是菜单栏的设计。JMenuBar里把系统功能分门别类组织好我把“系统管理”放在菜单最右侧包含“用户管理”“数据备份”“系统设置”这样前台工作人员日常操作时主要用工具栏和房态图管理员需要执行维护操作时才使用菜单职责清晰又不易误操作。数据备份菜单项通过调用SQL Server的BACKUP DATABASE命令实现直接拼接到ProcessBuilder执行sqlcmd命令操作完成后提示备份路径。5. 核心业务模块的代码实现与SQL细节界面层做完后真正的业务逻辑在Java代码与SQL交互的地方。JDBC连接和结果集处理是出错概率最高的区域这里给出我调通的一套完整写法。5.1 JDBC连接配置与连接池方案JDBC连接SQL Server关键是驱动类和连接URL要写对。我封装了一个DBUtil工具类统一管理连接、关闭、异常处理这样业务代码里不需要反复写Class.forName和try-catch。public class DBUtil { private static final String URL jdbc:sqlserver://localhost:1433;DatabaseNameHotelDB;encryptfalse; private static final String USER sa; private static final String PASSWORD 123456; static { try { Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps ! null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }注意URL里我加了encryptfalse。老版本驱动接口使用时会校验SSL证书如果不加这个参数在SQL Server 2019版本上会报“The driver could not establish a secure connection”错误这个坑很多人会踩到。连接池方面如果并发量不大直接用DriverManager就行如果后续要接多个客户端同时使用建议换成Apache DBCP或HikariCP。所有SQL操作都使用PreparedStatement不要用Statement拼接字符串。PreparedStatement不仅防SQL注入还能预编译提升性能。查询结果用ResultSet遍历后转换成对应的VO对象例如RoomVO包含房间号、房型、价格、状态这些属性数据访问层和界面层之间通过VO传递数据避免直接操作ResultSet。5.2 常见查询与统计SQL写法系统里需要展示一些统计报表比如某段时间的房间出租率和营业收入。这些用一条汇总SQL就能完成。日出租率统计可以这么做SELECT CONVERT(VARCHAR(10), CheckInTime, 120) AS CheckInDay, COUNT(DISTINCT RoomId) AS UsedRooms, (SELECT COUNT(*) FROM Room) AS TotalRooms, CAST(COUNT(DISTINCT RoomId) * 100.0 / (SELECT COUNT(*) FROM Room) AS DECIMAL(5,2)) AS Rate FROM CheckIn WHERE CheckInTime 2025-01-01 AND CheckInTime 2025-02-01 GROUP BY CONVERT(VARCHAR(10), CheckInTime, 120) ORDER BY CheckInDay;查询结果直接填充到JTable中。这里TabelModel建议自定义一个继承AbstractTableModel的类重写getValueAt方法配合ResultSet元数据动态生成列名这样所有查询结果都能用一个统一的表格组件展示代码复用率高。6. 踩坑实录与排查技巧做完整个项目后回看有几个坑是我当时折腾最久的写出来帮大家节省时间。6.1 SQL Server安装及连接失败处理SQL Server安装失败是老生常谈。安装时提示“Microsoft SQL Server安装失败。The required MSI package...”这类错误通常是系统缺少VC运行库或者之前的安装残留未清理干净。解决方法是到控制面板里把已安装的SQL Server组件全部卸载删除安装目录C:\Program Files\Microsoft SQL Server再下载最新的VC运行库安装后重试。如果是SQL Server 2012版本在Win10/11上安装要提前设置兼容模式为Windows 7。JDBC连接报“用户sa登录失败”时不要急着改代码先检查SSMS里是否启用了混合登录模式以及sa账号是否被禁用。端口连通性用telnet测试一下telnet 127.0.0.1 1433如果提示连接失败检查SQL Server配置管理器里TCP/IP协议是否启用。6.2 “ad hoc distributed queries”错误与跨服务器查询如果系统里用了OPENROWSET或OPENDATASOURCE这类跨服务器查询功能SQL Server会默认阻止并提示“阻止了对组件Ad Hoc Distributed Queries的statement OpenRowset/OpenDatasource的访问”。这个功能在宾馆管理系统里用得不多但如果你需要从Excel导入历史数据就绕不开。在线启用组件配置的语句是EXEC sp_configure show advanced options, 1; RECONFIGURE; EXEC sp_configure Ad Hoc Distributed Queries, 1; RECONFIGURE;注意这里是自用开发环境的配置生产环境不建议打开会有安全风险。我用这个功能做过一次Excel历史数据导入操作完马上关闭了这个配置项。6.3 Swing界面卡顿与刷新问题Swing是单线程模型所有UI更新必须在事件分发线程EDT中执行。我一开始在查询大数据量的按钮点击事件里直接执行SQL并循环添加到表格界面在查询期间完全卡死。后来把耗时操作放到SwingWorker后台线程执行查询完成后在done()方法里更新UI问题才彻底解决。记住一条原则任何超过100毫秒的数据库操作都不要直接在事件回调里执行。另外房间状态更新后要及时刷新用SwingUtilities.invokeLater调用房态按钮的重绘方法。如果不刷新会出现界面状态和数据库不一致的假象。我的解决方式是定义一个refreshRoomPanel方法每次入住或退房操作成功后重新查询所有房间状态并更新每个按钮的背景色和提示文本。6.4 其他值得注意的小问题SQL Server游标是个常见考点但在我们这个系统里基本不用。如果查询里要用逐行处理优先用JOIN和窗口函数替代游标性能差距非常明显。有次我在统计报表里用游标遍历所有入住记录计算每日收益几千条数据跑了好几秒换成窗口函数后瞬间出结果。中文乱码问题则要检查两点数据库排序规则是否为Chinese_PRC_CI_AS、JDBC连接URL是否设置了characterEncoding不过SQL Server用unicode编码Encrypt和TrustServerCertificate参数设置好之后很少出现中文乱码。SQL Server装在服务器上运行一段时间后内存占用很高Windows NT服务进程在任务管理器里看着吓人这是SQL Server默认会吃掉大量可用内存作为缓冲池可以在服务器属性-内存里设置最大服务器内存为物理内存的70%避免和前台系统抢内存。7. 项目扩展思路与部署经验分享最后聊聊做完基础功能之后还能怎么升级。宾馆管理系统做好标准版本后很多同学会考虑加功能这里我分享几个性价比比较高的扩展方向。第一个是把系统从单机版改成局域网多客户端版。SQL Server天然支持网络连接把JDBC URL里的localhost改成服务器IP防火墙放行1433端口其余代码完全不用改前台两台电脑就能同时录入订单了。这个改动很小但系统价值立刻不一样。第二个是增加图表统计模块。利用JFreeChart库把入住率趋势、房型营收占比用柱状图和饼图展示出来数据从第5.2节的统计SQL获取前端界面立刻变得高大上。JFreeChart的用法很简单拿数据集填进去就能生成图表。第三个是数据备份与恢复。在系统管理菜单里调用SQL Server的BACKUP和RESTORE命令每天定时自动备份到指定目录以防硬盘故障丢数据。这个功能做出来给答辩老师或领导演示时的专业感会强很多。实际上手的体验是这个项目一开始在界面上花的时间比数据库多得多后来调整思路先把数据库全部设计好再用统一的数据访问层接界面开发效率瞬间提升。代码里使用自定义的控制台日志输出类来调试些复杂的新增流程配合JDBC事务控制整段代码调通只用了两轮排查。希望看完这篇记录的你能少走一些弯路快速把项目跑起来有什么问题欢迎留言交流。本文还有配套的精品资源点击获取
返回列表