2026/10/11 13:04:44

酒店管理系统毕设:房态流转、数据库设计与Spring Boot实战

酒店管理系统毕设:房态流转、数据库设计与Spring Boot实战 简介这是一套面向Java毕业设计场景的酒店管理系统完整资料包涵盖毕业设计论文、答辩PPT、源代码、数据库及讲解视频主要帮助计算机类专业学生解决系统开发、毕业论文撰写和答辩准备等环节的实际问题。压缩包共13个文件包含3个MP4功能讲解视频、3张JPG项目截图、SQL数据库脚本、DOC/DOCX格式论文与进度表格、PPT答辩演示文稿以及打包好的Java源码ZIP和TXT使用说明整体大小约186.47MB。目前已有398人学习下载内容覆盖项目介绍与运行、管理员住店管理、餐饮相关管理三大功能模块并同步提供任务书、中期检查表等过程文档。借助这部分资料读者可以按视频目录逐步了解从环境搭建到功能演示的完整流程对照源码和SQL脚本理清数据库表结构及业务逻辑论文与答辩PPT则直接提供了毕业设计各阶段所需的文书框架和汇报思路方便在此基础上修改和复用也能帮助快速排查项目运行中的常见问题。1. 这个毕设题目难的不是写代码是解释不清房态怎么流转一个很常见的画面是毕设任务书下来选题写的是“酒店管理系统的设计与实现”学生手头也拿到了“论文答辩PPT源代码数据库讲解视频”的完整压缩包于是觉得万事大吉。结果呢三天时间耗在数据库连接串上两天耗在Tomcat端口上最后好不容易登录进去发现房间列表怎么点都是空的。这个题目的代码量在Java毕设里属于中等偏下但翻车率却常年排在前三。真正的分水岭不是会不会写CRUD而是能不能把“管理系统”这件事讲清楚房间状态怎么流转、订单从预订到退房经过哪些状态、报表里的营业额和收银记录能不能对上。这篇文章就顺着这条主线把这套毕设从跑起来到答辩讲明白。2. 拆解酒店管理系统功能树、状态流转与技术选型2.1 从一张房态图反推全部功能模块打开任何一家酒店的PMS系统第一屏永远是房态图。所谓房态图就是每一间房当前处于什么状态空净房、脏房、维修房、已预订、已入住、已退房。这六种状态不是随意枚举的它们构成一个完整的状态机而整个酒店管理系统的所有功能都是围绕这个状态机展开的。从这份状态机往前推就能画出功能树。前台模块负责预订、入住登记、换房、续住、退房结账房务模块负责打扫完成、房态置脏、维修登记收银模块负责押金、房费、餐饮消费、赔偿结算会员模块负责开卡、积分、折扣经理模块负责查看经营日报、月报、出租率。再往下拆每个模块都对应若干张表和若干条CRUD操作。比如“入住登记”这件事至少要触发房间状态从“空净房”到“已入住”的更新同时生成一条入住记录和一条订单记录。这棵功能树就是论文里的“需求分析”章节骨架。很多同学拿到现成项目之后第一篇论文草稿写的是“本系统包含用户管理、房间管理、订单管理”这种写法太空了。我一般会建议换个角度写先画一张房态状态流转图然后说“系统的核心是房态管理其余模块均围绕房态变化展开”。这句话一摆出来论文的层次感就出来了后面设计部分所有的表和模块都能挂在这棵树上。2.2 技术栈选型先看清手里的货再决定要不要换打开压缩包先看一件事源代码是什么框架。常见的情况有三种老一点的JSPServletJDBC属于手写DAO的风格中间一代是SSMSpringSpringMVCMyBatisXML配置一大堆再近一些是Spring Boot MyBatis/MyBatis-Plus。这三种技术栈没有绝对的好坏但要看你准备怎么用。如果手里的源码是SSM我建议不要大动干戈改造成Spring Boot。原因很实际SSM的配置分散在web.xml、spring-mvc.xml、mybatis-config.xml里这些配置文件本身就能作为论文“系统配置与部署”章节的写作素材。答辩老师如果问到“事务怎么控制的”你指着XML里的tx:advice就能讲清楚如果你改成Spring Boot配置确实少了但论文里那块就空了你得去补自动配置原理反而多写两千字。如果准备从零做那直接走Spring Boot MyBatis-Plus Thymeleaf/JSP的组合。Spring Boot负责把环境复杂度压下来MyBatis-Plus让DAO层的代码量少一半前端用JSP继续跑在Tomcat里和毕业设计环境兼容性最好。依赖关系大致是这样dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId /dependency依赖版本你根据手里Maven仓库实际能拉到的为准。MyBatis-Plus的3.5.x分支我用过比较多主要看它对JDK版本的兼容性如果本机是JDK 8尽量别用太新的版本。2.3 角色与权限边界三种人各看什么毕设系统通常做三种角色前台服务员、前台主管/经理、系统管理员。权限设计不用做成Spring Security那一套完整的RBAC用拦截器判断session里的用户角色就够了。权限边界按下面这样划答辩时一分钟就能讲清楚前台服务员房态查看、宾客入住、退房结账、预订登记、会员查询。经理房态查看、订单查询、营业日报/月报、房价调整、操作日志查询。管理员员工账号管理、房型管理、房间管理、系统参数配置。权限划分的逻辑要能说出理由前台接触的是“单笔交易”所以只需要房间和订单的写权限经理关注的是“汇总数据”所以只需要只读报表管理员管的是“基础数据”。论文里把这张权限表列出来需求分析部分就很站得住脚SQL设计里用户表加一个role字段就够用。3. 把项目跑起来环境配置与最小启动步骤3.1 拿到压缩包先做“目录体检”别急于点开IDEA很多同学的第一步是双击打开IDEA然后等它卡死。我习惯先解压用系统文件管理器把整个目录看一遍确认几样东西源码目录是src/main/java还是普通的src有没有webapp目录sql脚本在哪个位置有没有README或者数据库脚本.txt这种说明文件。把这几个信息列成清单源码结构Maven工程看pom.xml普通Web工程看WEB-INF/web.xml。数据库脚本通常是一个.sql文件里面包含建库、建表、初始插入语句。配置文件SSM项目看jdbc.properties或db.propertiesSpring Boot看application.yml或application.properties。部署方式是打WAR包扔Tomcat/webapps还是IDEA里配置Tomcat直接启动。这一步花十分钟后面省一小时。最怕的是连工程结构都没确认就直接开始配配到一半发现手里是一个Eclipse导出的普通Web工程IDEA里的导入方式和Maven工程完全不一样。3.2 导入工程与修改数据库连接配置IDEA里导入Maven工程用File - New - Project from Existing Sources然后选pom.xml。如果是普通Web工程直接选根目录IDEA识别成Web项目。导入后第一件事不是点启动而是检查依赖有没有全部拉下来IDEA底部进度条提示Maven import完成后在右侧Maven面板里双击clean和compile能过编译再继续。接下来改数据库连接。SSM项目的jdbc.properties长这样jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/hotel_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password123456Spring Boot项目的application.yml对应这样spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/hotel_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root password: 123456几个参数说清楚useSSLfalse关掉SSL握手MySQL 8.0默认开启SSL不关会报警告或直接失败serverTimezoneAsia/Shanghai是解决8.0的时区问题不写会报The server time zone value异常allowPublicKeyRetrievaltrue是配合caching_sha2_password验证插件用的这行的设置基本能覆盖MySQL 8.0的主要坑。还有最关键的这里的hotel_db必须和SQL脚本里的库名一致很多翻车现场是脚本里建库叫hotel配置里写hoteldb结果启动时告诉你数据库不存在。3.3 启动Tomcat跑通登录页与房间列表SSM项目在IDEA里配置Tomcat的常规做法是Run - Edit Configurations - - Tomcat Server - Local选本机Tomcat路径然后在Deployment页签点选择Artifact...把war exploded包加上Application context填/hotel。这个/hotel就是访问路径前缀后面访问登录页就是http://localhost:8080/hotel/login.jsp。Spring Boot项目更简单直接主类上点运行内置Tomcat默认端口8080。如果有端口冲突在application.yml里加一行server: port: 8081控制台看到这条日志就代表启动成功Tomcat started on port(s): 8080 (http) with context path 然后打开浏览器访问登录页用SQL脚本里插入的初始账号登录。登录成功先别急着演示点开“房间管理”或“房态图”确认房间数据能正常显示。如果页面能开但数据是空的回头查两件事第一SQL脚本执行时有没有报错第二账号是前台服务员还是管理员前台账号能不能看到房间列表。4. 表结构与核心SQL让数据在界面上有回应4.1 五张核心表的建表语句与其设计意图数据库设计部分是论文评审最关注的正文内容之一。酒店管理系统麻雀虽小但表之间的外键关系能完整体现第三范式。这里给出我自己做这套系统时最常用的五张核心表结构你拿到现成项目后可以对照看它的表设计是否一致。CREATE DATABASE IF NOT EXISTS hotel_db DEFAULT CHARSET utf8mb4; USE hotel_db; CREATE TABLE t_room_type ( id INT PRIMARY KEY AUTO_INCREMENT, type_name VARCHAR(50) NOT NULL, price DECIMAL(10,2) NOT NULL, breakfast TINYINT DEFAULT 0 COMMENT 含早餐:0否1是, bed_count INT DEFAULT 1 ); CREATE TABLE t_room ( id INT PRIMARY KEY AUTO_INCREMENT, room_no VARCHAR(10) NOT NULL UNIQUE, type_id INT NOT NULL, floor INT DEFAULT 1, status TINYINT DEFAULT 0 COMMENT 0空净房 1已入住 2脏房 3维修 4已预订, FOREIGN KEY (type_id) REFERENCES t_room_type(id) ); CREATE TABLE t_customer ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, id_card VARCHAR(18) NOT NULL, phone VARCHAR(20), member_level INT DEFAULT 0 ); CREATE TABLE t_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE, customer_id INT, room_id INT NOT NULL, check_in_date DATE NOT NULL, check_out_date DATE NOT NULL, total_amount DECIMAL(10,2) NOT NULL, status TINYINT DEFAULT 0 COMMENT 0已预订 1已入住 2已退房 3已取消 4已完成, created_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (customer_id) REFERENCES t_customer(id), FOREIGN KEY (room_id) REFERENCES t_room(id) ); CREATE TABLE t_check_in ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL, room_id INT NOT NULL, customer_id INT, deposit DECIMAL(10,2) DEFAULT 0, real_check_in_time DATETIME DEFAULT CURRENT_TIMESTAMP, real_check_out_time DATETIME, amount DECIMAL(10,2) DEFAULT 0, FOREIGN KEY (order_id) REFERENCES t_order(id), FOREIGN KEY (room_id) REFERENCES t_room(id) );这里几个设计细节值得答辩时展开讲。t_room.status用TINYINT存数字而不是直接存字符串是为了避免中文状态在存储和展示之间反复转换代码里用一个枚举类或Map来映射数字和文本。t_order.status的五个状态是订单生命周期的主线对应系统里的“预订→入住→退房→取消/完成”。t_check_in是整个表设计的核心——它专门存实际入住和退房时间和订单里的预计日期分离。这样设计的原因很现实客人可能提前入住也可能延住预计日期变更是常态如果直接改订单表账单审计就乱套了。4.2 入住与退房的SQL逻辑必须放在同一个事务里从界面上看入住登记只要填个姓名电话再点保存但底层至少三张表要联动。用MyBatis实现时这段逻辑要放到一个带事务的方法里。标准写法是Transactional(rollbackFor Exception.class) public void checkIn(CheckInVO vo) { // 1. 将订单状态从已预订修改为已入住 orderMapper.updateStatus(vo.getOrderId(), 1); // 2. 将房间状态从已预订/空净房修改为已入住 roomMapper.updateStatus(vo.getRoomId(), 1); // 3. 插入一条入住登记记录记录押金与实际上店时间 checkInMapper.insert(vo); }这段逻辑的关键在于Transactional注解。如果没有事务假设第二步房间状态更新失败而第一步订单状态已经提交了就会出现“订单显示入住、房间却还是空净房”的脏数据。这个场景在答辩时是很好的加分点你可以主动讲我在设计入住功能时将订单状态、房间状态和入住记录的更新放在同一事务中保证数据一致性。十五秒就能让老师看到你理解了“事务”在实际业务里怎么用。退房是反方向的操作先计算应付金额然后更新订单状态、房间状态、入住记录三处。Transactional(rollbackFor Exception.class) public void checkOut(CheckOutVO vo) { BigDecimal total computeAmount(vo.getOrderId()); orderMapper.updateStatus(vo.getOrderId(), 2); roomMapper.updateStatus(vo.getRoomId(), 0); checkInMapper.updateActualTime(vo.getCheckInId(), new Date(), total); }注意把房间状态置为0也就是空净房这样房态图上这间房直接变为“已退房/空房”保洁员看到后才能去置脏。如果你用的是旧房态体系退房还要分两步先置为脏房等保洁打扫完再置为空净房。这一步是业务流程和系统功能打通的关键不加这一步房态图永远不准。4.3 报表统计常用的两张SQL营业收入按天汇总与用房量统计答辩的时候老师大概率会问一句系统的报表功能是怎么实现的你要是只答“查数据库然后显示在页面上”基本等于没答。实际代码里最常见的是这两条统计SQLSELECT DATE_FORMAT(real_check_out_time, %Y-%m-%d) AS biz_date, SUM(amount) AS total_income FROM t_check_in WHERE real_check_out_time IS NOT NULL GROUP BY biz_date ORDER BY biz_date;这条查的是每一天实际产生的房费收入。注意条件里写的是real_check_out_time IS NOT NULL不是直接WHERE status 2。原因是退房结账的这一刻订单状态可能还没被事务更新完哪怕事务正确执行了如果哪天查出状态为“已完成”但实际退房时间为空这张报表和收银记录就对不上了。用时间字段而不是状态字段报表更稳定。用房量统计对应的是出租率这个指标在酒店管理里比收入还常被讨论SELECT COUNT(DISTINCT room_id) AS sold_rooms, (SELECT COUNT(*) FROM t_room) AS total_rooms FROM t_check_in WHERE real_check_in_time BETWEEN 2024-11-01 AND 2024-11-30 AND (real_check_out_time IS NULL OR real_check_out_time 2024-11-01);这段SQL的关键在于“在店”的判断一个客人11月29日入住、12月2日退房他在11月30日这天占了一间房统计月出租率时必须把他算进去。只看入住时间在当月是不够的必须同时判断退房时间为空或者退房时间不在当月之前。把这层逻辑写进论文的“报表模块设计”章节基本不会有人再质疑你报表是拼出来的。5. 五个典型坑与排查清单环境篇、数据篇、答辩篇5.1 现象登录页能打开点击登录后页面404原因提交表单的URL和Controller里的RequestMapping路径对不上常见于手动改了Controller的类名或方法名但没有同步改JSP里form的action另一种情况是Spring MVC的视图解析器配置里prefix/suffix写错导致return login解析后去查找一个不存在的/jsp/login.jsp。解决先看控制台有没有WARN级别的日志Spring MVC对没有映射的URL会打印No mapping found for HTTP request with URI /hotel/login。看到这句话去比对两个字符串浏览器地址栏的URL、控制器上的RequestMapping。如果控制台没有这条日志去检查spring-mvc.xml里的viewResolver配置prefix应指向JSP实际所在目录。日志是排查这类问题的第一现场不要白屏之后就去重编译。5.2 现象启动时抛异常提示Unknown database或Access denied for user rootlocalhost原因SQL脚本没有导入或者脚本里的库名和配置文件不一致Access denied通常是密码错误或者root账号的加密方式不被驱动支持。MySQL 8.0默认创建的用户使用caching_sha2_password旧版驱动无法识别。解决先执行SHOW DATABASES;确认有没有目标库。没有库就回到Navicat或命令行执行source 路径/数据库脚本.sql。有库但还是连不上检查配置文件用户名密码是否和本机MySQL一致顺手确认驱动版本MySQL 8.0的工程里不要用com.mysql.jdbc.Driver改com.mysql.cj.jdbc.Driver。这条报错信息是最容易在答辩前夜出现的原因往往是重装系统后MySQL密码变了但工程配置没跟着改。5.3 现象Tomcat启动成功但浏览器访问不到或者提示Port 8080 is already in use原因8080端口被占用常见占主是之前开发时残留的Tomcat实例、Oracle或其他Web服务也有一种情况是IDEA里配置了两个Tomcat实例前一个未停止。解决先用netstat -ano | findstr 8080Windows或lsof -i:8080macOS/Linux查出占用进程的PID强制终止掉或者最简单省事修改端口。SSM项目改Tomcat配置里的HTTP portSpring Boot改application.yml里server.port。顺手把首尾两个容易混淆的端口说清楚IDEA里Tomcat的JMX port和HTTP port是两回事改错了会报警JMX port already in use那个不是HTTP端口不要盯着它找问题。5.4 现象页面中文乱码控制台打印的SQL日志也乱码原因三处不一致导致乱码。第一处是数据库本身编码不是utf8mb4建表时没有加DEFAULT CHARSETutf8mb4第二处是JDBC连接串没写characterEncodingutf8第三处是JSP页面头部缺了pageEncoding或contentType设置里的编码声明。解决最稳的做法是三点同时检查。数据库层看建表语句的字符集配置文件看我前面写的url里的参数JSP页面在头部补上% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %还有一种隐蔽情况SQL脚本文件本身是UTF-8编码但导入时客户端用GBK读取导致已经进入数据库的数据就是乱码的。解决办法是在Navicat里新建查询窗口执行脚本前先确认窗口右下角的编码是UTF-8。数据进去之后再想清洗就非常痛苦了。5.5 现象答辩前三天发现论文截图和系统实际界面对不上原因压缩包里自带的论文通常是从别的题目改的截图里的酒店名称、房号、价格和当前系统的初始化数据完全不一致。答辩老师一翻论文再看你现场演示的页面立刻会觉得两个东西不是一个作品。解决这是最影响成绩的细节必须动手改。两条路都要走第一把系统的初始化数据改成论文截图里使用的同一套比如截图里是1001到1010房间系统里就建同样的房号第二论文的截图不重新截用一段脚本把数据库还原到初始状态。保证论文里的截图和现场演示时数据库的状态完全对应。养成本地留存一套“演示专用数据库脚本”的习惯答辩前跑一下脚本所有数据回到初始状态就不会出现论文截图和现场对不上的尴尬。6. 如何把项目改造成答辩时更拿得出手的版本两个必须加的亮点系统跑通只是及格线想要答辩时让评分老师觉得“这题做得扎实”我通常建议往上叠两个小亮点工作量不大但对论文和答辩表现都很有用。第一个亮点是“夜审功能”。行业里的真实酒店每晚要做一次夜审也就是当天营业数据结算、跨天房费自动累计。很多毕设系统完全没有这个概念。你可以在系统里加一张t_night_audit表每天凌晨自动跑一遍当天入住的订单为跨天未退房的订单增加一天房费。哪怕讲清楚“夜审计费”这件事本身就值不少分因为大部分同学根本不知道酒店有这个业务环节。第二个亮点是关键操作的日志记录。比如换房、改价、取消订单这三个敏感操作在代码里加一个切面对操作人、操作时间、操作内容进行记录对应一张t_operation_log表。不用做到分页查询那么复杂但论文里写“采用AOP实现操作日志”和普通CRUD完全是两个档次的工作量。AOP这个概念在Java课程里学过的人不少但用过的人不多你在这个项目里用了答辩的时候可以顺手讲一遍“切入点”“通知”这些词几分钟就能把氛围带起来。演示也要按这个顺序排先登录进房态图然后演示一条完整的业务链路——预订、入住、换房、退房结账、查看夜审后的营业日报最后点开操作日志指给老师看“这些记录是刚才那几步操作留下的”。控制在八分钟以内。整个过程绕开了那些空泛的“用户管理”“角色管理”只讲酒店业务自己关心的事老师听了会觉得这个系统是真的被业务验证过的。我每次带这类毕设项目讲解视频都会把演示顺序固定成这个闭环理由很简单答辩现场的意外大多来自临时操作而脚本化的流程可以提前把每一步都验证到位。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取