简介:这套基于Java开发的月亮湾酒店管理系统源码与配套数据库,主要面向需要完成课程设计、毕业设计或希望学习Java桌面项目开发的在校学生与初级开发者。资源压缩包共含350个文件、约9.74MB,其中既有56个Java源文件与60个class文件,也有10个jar依赖库和SQL Server数据库脚本,另附5份doc设计文档与3份ppt汇报材料,覆盖需求分析、概要设计、数据库设计、详细设计及用户手册等完整流程。数据库脚本基于SQL Server 2008 R2编写,通常2008以上版本均可执行。目前已有101人浏览学习,适合直接参考或二次开发。借助包内176个gif操作演示及分层源码,读者可快速掌握酒店预订、散客与团队登记、客户信息管理等核心模块的实现逻辑,并能结合ldf/mdf数据文件还原数据库环境进行运行验证。
1. 月亮湾酒店管理系统是什么:一个能落地运行的 Java + SQL Server 项目
亲测可运行是这个源码包最值钱的地方。月亮湾酒店管理系统是一套典型的 Java Web 单体项目,前端负责操作界面,后端用 Java 处理预订、入住、换房、退房、收银这些酒店日常业务,数据落在 SQL Server 数据库里。压缩包里除了工程源码,还带数据库文件或建表脚本,服务装好、数据库挂上就能跑起来。
这套东西最适合两类人:一是正在做课程设计或毕业设计的在校生,需要一个完整可讲解的业务样例;二是刚入行的 Java 开发,想看看真实酒店业务里一个订单从产生到结账是怎么被代码串起来的。它解决的核心诉求是:业务功能齐全、技术栈经典、规模刚好适合完整读一遍。
拿到压缩包,你要做的事就是:部署、读码、改造、验证。下面按这个顺序展开。
2. 解压源码之后先看什么:技术栈、目录结构与三组核心数据表
2.1 pom.xml 还是 lib 目录:一分钟判断框架类型
拿到压缩包第一件事是解压,然后花一分钟判断它到底是个什么结构的工程。这是后续所有步骤的前提,因为你后面要配的数据库连接、要用的部署方式,完全取决于它是 Maven 工程还是传统 Eclipse Dynamic Web Project。
unzip -q 月亮湾酒店管理系统源码.zip -d hotelws cd hotelws ls -la find . -maxdepth 3 -name "pom.xml" -o -name "*.sql" -o -name "*.properties" | head -30第一条命令把压缩包解到 hotelws 目录,避免直接解压在桌面把目录搞乱;第二条命令看工程根目录;第三条命令找关键文件。执行完你会看到三类结果:如果有 pom.xml,说明是 Maven 工程,依赖统一从中央仓库拉取,部署时用mvn clean package打成 war 包;如果没有 pom.xml 但 lib 目录下躺着几十个 jar,说明是传统 lib 方式,部署时要把工程结构原样拷进 Tomcat;如果两者都没有,那源码目录本身可能就是残缺的,后面要小心处理。
判断框架也有快捷方式。看 lib 里有没有 spring-webmvc、mybatis-spring 这类 jar,或者 pom 里有没有对应 dependency,就能知道是 SSM 框架(Spring + SpringMVC + MyBatis)还是更老的 JSP + Servlet + JDBC。标题只写了 Java 和 SQL Server,没有限定框架,所以要按实际解压结果为准。老项目最常见的是 JSP + Servlet + JDBC,这种对新手更友好,每个 Servlet 对应一个业务流程,阅读路径很直白;SSM 则要按 Controller → Service → Mapper → XML 四层去追。不管哪种,下面的检查顺序是一样的。
2.2 先找到这三样:建表脚本、JDBC 配置、启动入口
解压之后别急着点运行,先把三个东西找齐:数据库脚本、JDBC 连接配置、Web 启动入口。少一个都跑不起来,或者跑起来看不到数据。
- 数据库脚本:一般叫 init.sql、hotel.sql,有些包会直接带 mdf/ldf 数据库文件,这个后面单独说。
- JDBC 配置:文件名常见的是 jdbc.properties、db.properties,或者直接在某个 Dao/Servlet 类里写死。用一条 grep 命令就能定位所有出现数据库连接的位置。
- 启动入口:web.xml 在 src/main/webapp/WEB-INF 或 WebRoot/WEB-INF 下。看里面的 welcome-file 和 servlet-mapping,你就知道打开系统后第一个页面是什么,登录接口挂在哪个 URL 上。
我一般会先把 JDBC 配置全部拎出来看一遍:
grep -rn "jdbc:sqlserver\|com.microsoft.sqlserver\|mssql" --include="*.java" --include="*.properties" --include="*.xml" .这条命令把所有和 SQL Server 相关的代码行带行号列出来。重点看三处:连接串里的 IP 和端口是不是本机、数据库名是不是和后面要建的库名一致、用户名密码是不是 sa/123456 这类默认值。这里几乎必然要改,因为原作者写代码时用的是他本机的库名、密码和端口,你的环境不可能完全一样。
这一步一定要在部署前做,而不是报错后再回头找。有人先启动 Tomcat,发现 404 才想起没建数据库,结果绕了一大圈,还以为是 war 包的问题。
2.3 数据库表设计:房态、订单、会员怎么串起来
酒店管理系统的表结构大同小异,表名可能不同,但业务关系是一致的。月亮湾这类系统的核心表可以归成三组,理清这三组的关系,改代码时就不会迷路。
| 分组 | 常见表 | 承担职责 |
|---|---|---|
| 基础资料 | room_info / room_type | 房间号、房型、门市价、钟点房单价、楼层 |
| 业务单据 | reservation / order_info / check_in_record | 预订、入住登记、消费流水、结账记录 |
| 客户与权限 | member_info / user_info | 散客与会员信息、系统登录账号 |
把它们串起来的核心字段是房间状态和订单状态。room_info 里通常有一个 status 字段,取值一般是空闲、已预订、入住中、打扫中、维修中五种;每次状态流转都必须对应一张业务单据,比如预订单产生时把空闲改成已预订,入住登记时把已预订改成入住中。反过来,如果一张表里的状态没有单据支撑,那就是数据不一致。
看建表脚本时还有个细节值得注意:外键和索引。很多课程设计级别的源码为了省事不建外键,业务上“订单必须关联到存在的房间”这个约束就完全靠代码自己保证。这种设计排查问题时会比较痛苦,因为数据库层不拦你插入脏数据。理解这个背景之后,你改代码时要格外小心状态更新的顺序,这也是第四章要展开讲的重点。
3. 从零部署到能访问:SQL Server 附加数据库与 JDBC 连接参数实战
3.1 环境搭配:JDK、Tomcat、SQL Server 版本的常见组合
这类老项目对环境版本特别敏感,不是配置对就行,是版本得在一个时代里。JDK 17 跑老 EJB 项目直接起不来,JDK 1.6 编译的 class 扔进 Tomcat 10 里报 Servlet 包冲突,这类问题我都碰过。保险的做法是照着老项目的年代组合搭:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8 | 兼容性最好,老项目基本都能跑 |
| Tomcat | 8.5 或 9.0 | 支持 Servlet 3.1/4.0,对应 JDK 8 |
| SQL Server | 2012 / 2014 / 2019 Express | Express 免费,功能足够这套系统用 |
| 连接工具 | SSMS 或 Navicat | 图形化看数据比命令行直观 |
SQL Server 版本不需要刻意追 2022,2019 Express 完全够用。网上还在搜“sql server 2012下载”,说明 2012 在课程设计圈仍在服役,但它在 Windows 10/11 新系统上偶有兼容性问题。我一般直接上 2019 Express,安装包从微软官方渠道下载,装完基本一步到位。
安装 SQL Server 时有个选项必须注意:身份验证模式。建议在第一屏就选“混合模式(SQL Server 身份验证和 Windows 身份验证)”,并给 sa 设一个记得住的密码。绝大多数 JDBC 连接串写死user=sa,如果你装成纯 Windows 认证,连接必失败,后面 5.3 节还会展开讲。
3.2 附加数据库而不是盲跑脚本:两种恢复方式的取舍
数据库这步有两种典型形态:压缩包里给的是 mdf/ldf 文件,或者给的是 .sql 建表脚本。处理方式完全不同。如果给的是 mdf/ldf,最省事的是 SSMS 图形化附加,或直接执行下面这段 SQL:
USE [master] GO CREATE DATABASE MoonBayHotel ON (FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\MoonBayHotel.mdf'), (FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\MoonBayHotel_log.ldf') FOR ATTACH GO这段脚本把已存在的物理数据库文件挂到当前实例。注意两点:第一,FILENAME 里的路径必须与实际文件位置一致,文件在 D 盘就换成 D 盘绝对路径,不要用相对路径;第二,mdf 和 ldf 要成对出现,只有 mdf 没 ldf 时 SQL Server 会尝试重建日志,但成功率取决于文件是否正规关闭过。我习惯先把文件拷到 SQL Server 的 DATA 目录再附加,少踩一个文件权限的坑。
如果给的是 .sql 建表脚本,直接在 SSMS 新建查询执行:
CREATE DATABASE MoonBayHotel; GO USE MoonBayHotel; GO -- 后面是逐段的 CREATE TABLE 和 INSERT 语句这里有隐藏风险:脚本里带中文注释或中文初始数据时,编码不对会产生乱码。SQL Server 的做法是在建库时指定排序规则:
CREATE DATABASE MoonBayHotel COLLATE Chinese_PRC_CI_AS; GOChinese_PRC_CI_AS 是简体中文、不区分大小写、区分重音的排序规则,兼容绝大多数中文系统的数据存取。建表脚本里如果已写排序规则,就不要重复指定。
注意:执行 .sql 脚本时若看到中文初始数据变问号,先确认连接编码,再确认排序规则,不要急着重新建库。
3.3 JDBC 连接串与驱动 jar:4 个必须检查的参数
数据库建好之后,下一步让 Java 代码连上去。老项目一般有个 jdbc.properties,内容大致长这样:
jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc.url=jdbc:sqlserver://127.0.0.1:1433;DatabaseName=MoonBayHotel;encrypt=false;trustServerCertificate=true jdbc.username=sa jdbc.password=123456逐行解释:driver 是微软官方驱动入口类,这个类名从 JDBC 4.0 开始没变过;url 里 1433 是 SQL Server 默认端口,DatabaseName 与实际建的库名完全一致;encrypt=false 和 trustServerCertificate=true 这两个参数是给新驱动准备的——微软 JDBC 驱动 9.0 及以后默认启用传输加密,老系统的证书多半是自签的,不关加密就会握手失败。username 用 sa,password 就是装 SQL Server 时设的那个,别留空。
驱动 jar 是另一个高频翻车点。老项目 lib 里放的是 sqljdbc4.jar,如果用的 SQL Server 2019 以上,建议换成 mssql-jdbc-8.2.2.jre8.jar 或更高版本,太老的驱动不认识新实例返回的登录令牌。替换 jar 就两步:删旧 jar、拷新 jar 进 lib 目录,然后清 Tomcat 缓存。不要新旧共存,类重复加载会成为新的黑匣子。
改完这些,运行前用一条命令确认配置真的生效:
grep -rn "127.0.0.1\|localhost" --include="*.properties" . | grep -i sqlserver这条命令只列出数据库连接相关的 host 配置,避免把业务上的 localhost 也挖出来。这里看到的 IP 才是代码实际会去连的地址,凡是写死远程 IP 的一律改成 127.0.0.1。
3.4 启动 Tomcat 后先看这里的日志,而不是刷新浏览器
部署到 Tomcat 有两种常见方式:Maven 工程用mvn clean package打成 war 丢进 webapps;传统工程在 IDE 里配置 Tomcat Server 直接发布。不管哪种,启动之后都要先看日志,不要对着浏览器来回刷新。
日志位置在 Tomcat 的 logs 目录,Linux 看 catalina.out,Windows 看 catalina.<日期>.log。启动成功会有类似输出:
信息: Server startup in [4,567] milliseconds如果看到ClassNotFoundException,说明依赖 jar 缺失或版本冲突,回去检查 lib 目录。如果是Connection refused或Login failed for user 'sa',那就是 3.3 节那几个参数没对上,按清单逐项核对。
页面访问路径取决于 war 包名。包名 hotel.war 对应http://localhost:8080/hotel/,具体登录页看 web.xml 的 welcome-file。Tomcat 默认端口 8080 被占用时,日志会直接打印端口冲突,要么杀掉占用进程,要么在 server.xml 改 Connector 的 port 后重启 Tomcat。到这一步,系统能打开、能登录、能看到菜单,部署环节就算真正跑通了。
4. 读懂入住与退房业务链路:事务边界与房态更新怎么写才不出错
4.1 入住登记:插入订单、更新房态为什么必须在一个事务里
拿到能跑的系统,接下来要读懂核心链路。酒店管理系统最重要的不是登录,而是从入住登记到退房结账这一条链路。链路涉及的代码量不大,但几乎所有业务 bug 都集中在这几条方法里。先看入住登记的典型写法:
@Service public class CheckInService { @Autowired private RoomMapper roomMapper; @Autowired private OrderMapper orderMapper; @Transactional(rollbackFor = Exception.class) public Long doCheckIn(CheckInRequest req) { // 1. 检查房间状态 Room room = roomMapper.selectByRoomNo(req.getRoomNo()); if (!"空闲".equals(room.getRoomStatus())) { throw new BizException("房间当前状态:" + room.getRoomStatus() + ",无法入住"); } // 2. 插入入住订单,状态置为“在住” Order order = new Order(); order.setRoomNo(room.getRoomNo()); order.setCustomerName(req.getCustomerName()); order.setStartTime(new Date()); order.setStatus("在住"); orderMapper.insert(order); // 3. 更新房间状态 roomMapper.updateStatusByRoomNo(req.getRoomNo(), "入住中"); return order.getOrderId(); } }这段代码里最关键的不是任何一行 SQL,而是方法上的@Transactional(rollbackFor = Exception.class)。它保证第 2 步插入订单和第 3 步更新房态要么一起成功,要么一起回滚。如果去掉这个注解,插入订单成功之后更新房态失败,就会出现“订单存在但房间仍显示空闲”的脏数据。酒店业务里这意味着同一间房可能被二次开单,后果比想象严重。
一个值得注意的细节是rollbackFor = Exception.class。Spring 默认只对 RuntimeException 回滚,如果业务异常是受检异常,不加 rollbackFor 事务不会回滚。老项目里经常漏这个参数,面试里这也是经典的 Java 开发工程师面试题。看到业务方法有 @Transactional 但没写 rollbackFor,先想想调用链上的异常类型再决定。
4.2 房态更新用条件更新,避免并发把两单开进同一间房
上一小节的写法还有并发隐患:先查房间状态,再插订单,最后更新房态。两个前台同时操作同一间房,理论上都可能通过第一步的状态检查,然后各自插单,房态只反映最后一次更新的结果。解决方式不复杂,把 UPDATE 语句改成带状态条件:
// 原子地完成“检查状态并更新” int rows = roomMapper.updateStatusByRoomNo(req.getRoomNo(), "入住中", "空闲"); if (rows == 0) { throw new BizException("房间已被占用,请刷新后重试"); }对应 MyBatis XML 里的 SQL 是:
<update id="updateStatusByRoomNo"> UPDATE room_info SET room_status = #{newStatus} WHERE room_no = #{roomNo} AND room_status = #{expectedStatus} </update>这个写法的核心是让数据库自己保证条件更新:只有当前状态还是“空闲”时才把状态改成“入住中”。两个人同时发起时,SQL Server 的行锁会让后一条 UPDATE 等待;前一条提交后,后一条执行时 WHERE 里的room_status = '空闲'已经不成立,影响行数为 0,服务层就能抛出异常而不是继续插单。
注意,这里不能只用“查询检查再更新”,因为检查到更新之间有时间窗口。Java 锁或分布式锁当然也行,但对单机部署的课程设计项目来说,把状态字段放进 UPDATE 的 WHERE 是最简单、最不容易翻车的方案。改成条件更新后,原代码里第一步的“检查房间状态”可以保留,作为友好提示,真正的屏障是 UPDATE 的返回值。
提示:UPDATE 影响行数为 0 时一定要抛异常,不能默默返回成功,否则前台会以为开房成功了。
如果你在源码里看到的房态更新是UPDATE room_info SET room_status = '入住中' WHERE room_no = ?这种不带状态条件的,说明系统在并发上有洞。要不要补看定位——只做演示可以不补,但答辩时老师最爱问“同时开同一间房怎么办”,补上更稳。
4.3 换房、续住与退房结账:三个容易改崩溃的边角业务
相比入住登记,换房、续住、退房更容易把人绕晕,因为它们都跨两张以上的表做状态一致性维护。换房的本质是在同一个订单号下,把旧房间改成打扫中、新房间改成入住中,同时把订单里的 room_no 改掉。很多人只改了房间表,忘了订单表上的房间号,结果前台显示新房间,报表按订单号查出旧房间,对账对不上。
退房结账是数学题出错的重灾区。时长计算如果把毫秒差除以小时再除以 24 当作天数,遇到跨天就很麻烦。酒店业常见规则是“过夜按一天,钟点房按小时,超出部分按时计价”,代码里通常要写分段逻辑:
public BigDecimal calcRoomAmount(Date start, Date end, BigDecimal dailyPrice, BigDecimal hourlyPrice) { long diffMs = end.getTime() - start.getTime(); long hours = diffMs / (1000 * 60 * 60); long days = hours / 24; long remainHours = hours % 24; if (remainHours == 0) { return dailyPrice.multiply(BigDecimal.valueOf(days)); } // 剩余不足 4 小时按钟点价,超过 4 小时按全天价,行业常见做法 if (remainHours <= 4) { return dailyPrice.multiply(BigDecimal.valueOf(days)) .add(hourlyPrice.multiply(BigDecimal.valueOf(remainHours))); } return dailyPrice.multiply(BigDecimal.valueOf(days + 1)); }这段代码把计价规则做了一层简化。改源码时要先读透项目里原本的时间常量,比如 dayLimit、freeMinutes 这类字段,再决定用哪种分段。特别注意 BigDecimal 是必须的,double 在金额计算里会出现 0.1 + 0.2 != 0.3 的精度问题,这是 Java 基础里最容易被真实业务“现形”的知识点。
换房、续住、退房还有一个共同点:都应该做成带状态判断的业务方法,而不是直接改库。退房要把订单从“在住”改成“已离店”,房间改成“打扫中”,账户做退款结清。如果退房方法里漏掉退押金,客户的押金就凭空消失了。读懂这些代码之后,你改业务时至少知道改哪几个地方,不会只改页面不改逻辑表。
5. 部署与二次开发的避坑清单:5 条 SQL Server + Java 的典型故障
5.1 连库就报 Connection refused?先检查 TCP/IP 协议
现象:项目启动日志或页面报错,异常信息里有java.net.ConnectException: Connection refused: connect,指向 1433 端口。
原因:SQL Server 安装后默认可能禁用了 TCP/IP 协议,或端口不是默认 1433,或 SQL Server Browser 服务没启动。这个问题在 SQL Server 2012 之后的版本里普遍存在,安装向导默认勾选的服务不够“通用”。
解决:打开 SQL Server Configuration Manager → SQL Server 网络配置 → 找到实例协议,右键 TCP/IP 选择“启用”。然后在 TCP/IP 属性 → IP 地址页签里确认 IPAll 端口为 1433,重启 SQL Server 服务。改完用telnet 127.0.0.1 1433验证端口通没通,再重启 Tomcat。这是排查 SQL Server 连接问题的第一动作,网上的安装教程一般不会提默认禁用这个坑。
5.2 附加数据库时报错:权限不足和路径不对是两个主因
现象:执行 FOR ATTACH 报错,常见 5123 或 5120,信息里带Access denied或File not found。
原因:一是 mdf/ldf 文件放在桌面或下载目录,SQL Server 服务账号没有目录读取权限;二是文件名或路径带中文、带空格,或文件被占用没释放。
解决:把 mdf 和 ldf 复制到 SQL Server 实例的 DATA 目录,再用 3.2 节的脚本附加。复制前确保没有 SSMS 连接占用该文件。如果非要在原位置附加,可以给目录加权限,但我不建议,局域网共享目录下这么干有安全风险。
5.3 sa 密码过期或登录失败:混合模式与密码策略一起处理
现象:连接串写 sa,启动报Login failed for user 'sa';或者某天突然提示“密码已过期,必须更改”。
原因:sa 账号受 Windows 密码策略约束,系统开启密码过期检查,长期不登录或超过最长使用期限就会触发过期;更常见的是一开始装成 Windows 身份验证模式,sa 被禁用。
解决:先用 Windows 身份验证登录 SSMS,在服务器属性 → 安全性里改成“SQL Server 和 Windows 身份验证模式”,然后执行:
ALTER LOGIN sa WITH PASSWORD = 'YourNewPassword'; GO ALTER LOGIN sa WITH CHECK_POLICY = OFF; GO第一条重置 sa 密码,第二条关闭密码过期策略,避免下次又到期。CHECK_POLICY = OFF只在开发和课程设计环境用,生产库这样做不合规。改完要重启 SQL Server 让认证模式生效。这条经验对应很多人搜的“sql server 2012密码到期”,我处理过不止一次。
5.4 新版驱动连库报 SSL 错误:驱动版本与数据库版本要匹配
现象:换新驱动后报The driver could not establish a secure connection,或“驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接”。
原因:微软 JDBC 驱动 9.0 开始默认要求加密通信,SQL Server 2019 默认返回加密支持,但没有配置有效证书时握手失败。老项目驱动停留在 6.x/7.x,行为不同,一升级就对不上了。
解决:在 JDBC URL 加encrypt=false;trustServerCertificate=true。加完仍报错就把驱动降回 8.2 或 7.4 版本,与 SQL Server 2012/2014 更稳。别为了消除报错盲目升级驱动,驱动与数据库有版本对应关系。老系统能跑就不要动这个 jar,动了就要验证登录、增删改查、中文编码三条链路。
5.5 数据库文件越来越大:事务日志与 WRITELOG 的坑
现象:C 盘空间持续告警,数据库文件明显膨胀,写入变慢,SSMS 里能看到大量WRITELOG等待类型。
原因:数据库默认是完整恢复模式,每次事务的日志都保留,长期不备份不收缩,日志文件就会越滚越大。课程设计项目一般不需要做时间点恢复,保留完整日志没有意义,只占磁盘。
解决:把数据库改成简单恢复模式并收缩文件:
ALTER DATABASE MoonBayHotel SET RECOVERY SIMPLE; GO DBCC SHRINKDATABASE (MoonBayHotel); GORECOVERY SIMPLE让 SQL Server 自动复用日志空间,不再无限增长;DBCC SHRINKDATABASE把已膨胀的文件缩回去。改完后定期观察文件大小,如果又涨起来,检查是否有长事务或循环写入的代码逻辑。
6. 跑通之后先做这三处改造,再考虑拿得出手
6.1 用户密码加密
默认账号表里的密码基本是明文,第一件事就是改成加盐的 SHA-256:
public static String saltAndHash(String rawPassword, String salt) { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update((salt + rawPassword).getBytes(StandardCharsets.UTF_8)); return HexFormat.of().formatHex(md.digest()); }保留原密码字段,新增 passwordSalt,登录校验改成取盐再哈希比对。迁移老数据时统一生成随机盐,首次登录强制改密。
6.2 把拼接 SQL 换成参数化查询
老 JSP + Servlet 项目里最刺眼的是"select * from user_info where username='" + name + "'"这类拼接。换成 PreparedStatement:
Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement( "SELECT * FROM user_info WHERE username=? AND password=?"); ps.setString(1, username); ps.setString(2, passwordHash); ResultSet rs = ps.executeQuery();这一步改完,登录接口的注入路径就堵死了。改完记得密码字段的校验换回 6.1 节的哈希结果,不然又回到明文对比。
6.3 用一条完整业务链路验证改动
改完后别只看登录页,把系统当酒店真实营业流程过一遍:开单 → 入住 → 换房 → 续住 → 加消费 → 退房结账 → 查日结报表,每一步都检查房态表的状态变化。特别验证退房后房间状态从“入住中”回到“打扫中”,打扫完再回到“空闲”。这条链路走通,改动才算没破坏原有业务。顺便核对订单金额和押金扣款是否一致,数字对不上说明 BigDecimal 那段被改漏了。
我习惯在改完任何一处业务代码后,先手动走一遍这套链路回测十分钟再提交,这个习惯是从我改坏过一次退房逻辑、害得前台手动调账之后养成的。这个压缩包的意义不在于能跑,而在于你能顺着一套完整的酒店业务,把 Java 和 SQL Server 之间的配合讲明白。希望帮到你。
本文还有配套的精品资源,点击获取