简介:这是一份基于SSM框架与Vue/JSP前端技术构建的医院门诊挂号系统完整项目,适合Java Web方向学习者、毕业设计开发者以及医院信息系统入门人员。系统覆盖患者挂号、科室管理、医生排班等核心业务,后端采用Spring+SpringMVC+MyBatis分层架构,前端结合Vue的响应式交互与JSP动态页面,并适配JDK1.8、Tomcat7+和MySQL5.7运行环境。压缩包大小约15.3MB,内包含可部署的完整项目源码、数据库初始化脚本、功能说明文档等,便于直接导入开发工具进行调试与二次开发。该资源已有2736人学习下载,项目经过严格调试,运行稳定。通过源码可掌握SSM整合流程与前后端交互细节,借助数据库脚本可快速搭建本地数据环境,功能文档则能帮助使用者高效理解系统模块和操作方式,整体是兼具学习价值与毕业设计参考价值的完整资源。
1. 医院门诊挂号系统值得跑一遍:一个 SSM 老项目拆开后的东西
做毕业设计或企业内部练习项目时,医院门诊挂号系统是出现频率最高的题目之一,它不像电商系统那样堆砌商品和订单概念,而是围绕「科室-医生-号源-挂号记录」这条单一业务主线,把增删改查、状态流转、权限控制全部串起来。这套 ssm9008 医院门诊挂号系统 + jsp,后端是 Java 搭配 SSM(Spring、SpringMVC、MyBatis),前端同时用了 JSP 和 Vue,数据库落在 MySQL 5.7 上,附带的资源包里有完整源码、数据库脚本和功能文档。对正在找毕设方向、或者想把 SSM 整套流程从配置到部署跑通的人来说,它最直接的价值就是「不用从零搭骨架」,把项目导入 Tomcat 改完数据库连接就能看到真实业务运转。这套资源适合两类人:一类是打算拿它做毕业设计、需要尽快跑起来并二次扩展的学生;另一类是刚接触 SSM 整合、想看懂一个完整项目如何分层协作的 Java Web 开发者。
2. 先把工程看明白:SSM 三层结构与数据库表设计的落点
2.1 SSM 在这个系统里各自管哪一段
打开源码包以后,第一件事不是急着启动,而是先看清目录结构。常见的 SSM 后端工程会按 controller、service、mapper、entity/pojo 分层,这套医院门诊挂号系统也遵循同样惯例。Spring 负责组件的依赖注入和事务管理,SpringMVC 负责把浏览器请求分发给对应的 Controller 方法,MyBatis 负责把 Java 对象和数据库表记录互相映射。三者拆开以后,业务代码写起来会非常「薄」:Controller 只接参数和返回页面,Service 只写业务规则,Mapper 只碰 SQL。
拿到工程后第一步应该先确认目录结构是否完整,我一般会在 IDEA 里直接查看,或者在项目根目录跑一段命令把关键目录打出来:
# 在项目根目录执行,列出主要源码结构与资源目录 find . -type d \( -name controller -o -name service -o -name mapper -o -name entity -o -name resources -o -name jsp -o -name webapp \) | sort输出的目录一般包括controller、service、mapper、entity、resources、webapp等。resources里存着 Spring 配置文件、MyBatis 映射文件和数据库连接配置;webapp下放 JSP 页面和静态资源。这些目录的职责划分很直观:如果你要改挂号流程的校验规则,去service层找逻辑;如果发现某个页面取不到数据,先看controller层有没有对应的方法,再看mapper的 SQL 是否正确。从工程结构就能推断出一个项目的维护成本,结构越清晰,二次开发时越少踩雷。
2.2 挂号系统的核心表与状态设计
门诊挂号系统的数据模型比一般管理系统的表多一层「状态流转」设计,这是这套源码里最值得读的部分。典型的表至少包含四类:用户/患者表、科室表、医生表/排班表、挂号记录表。挂号记录是整个系统的核心,它必须记录挂的是哪个科室、哪位医生、哪一天、哪个时段,以及当前这笔挂号处于什么状态(已挂号、已就诊、已取消)。数据库脚本里通常还会加上创建时间和更新时间字段,方便排查问题。
| 表名 | 核心字段 | 关键作用 |
|---|---|---|
| user / patient | id、username、password、phone | 登录与权限识别 |
| department | id、name、intro、status | 科室展示与筛选 |
| doctor | id、name、department_id、title、schedule | 医生信息与排班 |
| registration | id、user_id、doctor_id、visit_date、time_slot、status | 挂号单核心状态流转 |
这里要注意status字段的设计。在挂号场景里,数据不是「插入就完事」,而是「插入后还要更新状态」。比如用户取消挂号时,很多新手会直接 DELETE 记录,但正规系统设计是保留记录、把状态改成已取消,这样医院在后面对账和统计爽约率时才有数据可查。如果你拿到这套源码后发现registration表里有 status 字段但页面没有取消功能,这通常不是缺陷,而是留给你的扩展点——把「取消」动作做成状态更新就是一次很好的二次开发练习。
2.3 数据脚本导入与初始化数据检查
源码包里的 SQL 脚本一般包含建库、建表和初始化数据三部分。不要直接双击用记事本打开看,更推荐先建好库再逐段导入。MySQL 5.7 下导入时最常踩的坑有两个:一个是脚本文件用 UTF-8 保存,但终端默认字符集不一致导致中文乱码;另一个是导入顺序出错,先导入有外键依赖的表导致报错。稳妥的顺序是先建库,再导全部表,最后检查初始化数据量。
# 登录 MySQL 5.7,并创建专用数据库(假设脚本里库名为 hospital) mysql -uroot -p123456 -e "CREATE DATABASE IF NOT EXISTS hospital DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 导入数据库脚本,注意 --default-character-set 要和脚本编码一致 mysql -uroot -p123456 --default-character-set=utf8mb4 hospital < db_hospital.sql # 检查核心表数量和初始化数据行数 mysql -uroot -p123456 -e "USE hospital; SHOW TABLES; SELECT COUNT(*) FROM registration;"CREATE DATABASE后面必须带上DEFAULT CHARACTER SET utf8mb4,这样做是为了防止后续表里存中文姓名、科室名时出现乱码。导入时--default-character-set=utf8mb4这个参数很关键,它告诉 MySQL 客户端脚本文件本身是 UTF-8 编码,按这个编码解析后再写入表。最后那条SELECT COUNT(*)是为了验证初始化数据是否真实存在——很多项目看起来启动成功但页面是空的,就是因为数据没导进去,所以这个检查步骤不能省。
2.4 连接配置:改对一处就能少折腾半小时
工程里数据库连接配置一般写在resources下的jdbc.properties或db.properties文件里,内容很固定,无非是驱动类名、连接地址、账号、密码。但连不上库的案例里,九成问题出在「URL 配置和 MySQL 版本不匹配」上。MySQL 5.7 的驱动类名是com.mysql.jdbc.Driver,如果用 MySQL 8+ 的驱动,就得换成com.mysql.cj.jdbc.Driver并额外加时区参数。这套项目约束在 MySQL 5.7+,所以按老驱动配置即可。
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/hospital?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=123456useUnicode=true&characterEncoding=utf8这两段作用是让 Java 与 MySQL 之间传输中文时按照 UTF-8 编码解析,避免中文乱码。useSSL=false是关闭 SSL 加密连接,开发环境用不上加密,开着反而会多一次握手警告。如果你的密码里有特殊字符,比如@或#,URL 里不会受影响,但 properties 文件里的赋值可能截断,建议先用纯数字密码跑通再换正式密码。
3. 从零把系统跑起来:JDK1.8、MySQL 5.7、Tomcat7 的配置顺序与启动验证
3.1 环境匹配逻辑:为什么是 JDK1.8 配 Tomcat7
这套系统的运行环境是 JDK1.8 + Tomcat7 + MySQL 5.7,这个组合不是随便拍的,而是许多年毕设项目的「黄金组合」。JDK1.8 提供了 Lambda 表达式等新特性,同时也兼容旧语法;Tomcat7 对 JSP/Servlet 的支持非常稳定,对老项目的兼容性比 Tomcat8/9 更稳;MySQL 5.7 是当时用得最广的版本,SQL 语法和驱动都相对成熟。不要一上来就想着用 JDK17 或 Tomcat10 跑,因为 Spring 旧版本和 JSP 的编译方式在不同容器上行为差异很大,轻则报错,重则整个页面白屏。
安装顺序建议是:先装 JDK1.8 并配好JAVA_HOME,再装 MySQL 5.7 并用 Navicat 或命令行建库导数据,最后解压 Tomcat7。Tomcat 本身是绿色软件,解压即用,不需要安装。配完环境后可以在命令行验证版本:
# 检查 Java 版本是否为 1.8 java -version # 检查 Tomcat 是否可启动(在 tomcat/bin 目录下) startup.batjava -version输出里应该包含1.8字样,注意不要出现多个 JDK 混乱的情况——一起装的 JDK11 或 JDK17 会改变默认版本。startup.bat在 Windows 下启动 Tomcat 后,浏览器访问http://localhost:8080能看到 Tomcat 默认首页,就说明容器本身是健康的。这一步检查很重要,因为很多人跳过它,直接把项目丢进去,最后根本分不清是项目问题还是 Tomcat 环境问题。
3.2 用 IDEA 导入工程:手动配置才是关键
拿到源码后,在 IDEA 中选择Open打开项目目录,如果发现代码没被识别为 Maven 工程(依赖没自动下载),先去检查pom.xml是否存在。SSM 项目通常会用 Maven 管理 Jar 包依赖,但有些毕设工程直接把 Jar 放在WEB-INF/lib下,没有用 Maven。这种情况不用慌,在 IDEA 里右键工程选择Add as Maven Project即可;如果用普通 Web 工程方式打开,则需要在Project Structure里把编译输出目录和依赖指向lib目录。
由于原项目约束在 Tomcat7+,发布方式最好用 IDEA 的 Tomcat 集成或者直接打包成 WAR 丢进 Tomcat 的webapps目录。社区里用 IDEA 直接配 Tomcat 的比较多,配置项如下:
# 在 IDEA 的 Edit Configuration 里配置 Tomcat Server # 1. Application server 选择本地 Tomcat7 根目录 # 2. Deployment 中添加 artifact 并设置 Application context 为 /hospital # 3. Server 面板中设置端口为 8080Context路径要特别注意,它决定了浏览器访问地址。如果你配的是/hospital,访问入口就是http://localhost:8080/hospital;如果忘记设置直接默认/,页面里写死的链接就可能全部对不上路径。我的习惯是把 Context 配成项目名,并且提前把数据库名也保持一致,这样路径、库名、项目名三者统一,排查问题时少绕很多弯。
3.3 启动后的三层验证法
系统启动后,不要先去点页面上的功能,而是按顺序验证三件事:第一,登录页能不能打开;第二,能不能登录成功;第三,挂号主流程能不能走通。如果登录页都打不开,问题多半在 Tomcat 发布或 SpringMVC 的web.xml配置上,常见的是默认 Servlet 映射把静态资源拦截了。如果登录打不开但页面能加载,问题多半在数据库连接或者 SQL 语句上,看 IDEA 控制台里的异常堆栈就能定位。
http://localhost:8080/hospital/login.jsp登录页能打开后,先用初始化数据里提供的账号登录一次,再点进挂号页面,观察挂号记录是否能写入。这里有两个最常用的数据库排查命令:
-- 查看当前所有连接,确认不是端口或白名单问题 SHOW PROCESSLIST; -- 查看挂号表数据是否在增长 SELECT id, user_id, doctor_id, status, create_time FROM registration ORDER BY id DESC LIMIT 10;SHOW PROCESSLIST的作用是看数据库到底有没有收到应用发来的请求,如果这里一片空白,说明问题还在 Java 段,没走到 SQL;如果有Query状态被锁住,则要考虑是否事务没提交或者表被锁了。最后那条SELECT是观察数据写入情况用的,拿它和页面上显示的内容对照,能很快定位是前端显示问题还是后端存储问题。
3.4 端口冲突与 Tomcat 内存配置
启动 Tomcat 时最容易翻车的是端口被占用。8080 经常被各种开发软件占用,也许你之前跑过别的服务没关干净。解决方式有两个,一是找到占用进程直接停掉,二是改 Tomcat 的端口配置。改端口需要编辑conf/server.xml里的<Connector>节点,找到如下位置:
<!-- conf/server.xml 中的连接器配置 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />port="8080"就是访问端口,改成8081后重启 Tomcat 即可。改端口的同时,IDEA 里配置的 URL 也要同步修改,否则你访问的还是 8080 端口旧服务。Tomcat 内存方面,如果系统在跑挂号报表或查询大列表时卡顿,可以在catalina.bat(Windows)或catalina.sh(Linux)中设置JAVA_OPTS,常见配置如下:
# Linux 下在 catalina.sh 开头加入 CATALINA_OPTS="-Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256m"-Xms和-Xmx控制堆内存的初始和最大值,-XX:PermSize与-XX:MaxPermSize是永久代大小,JDK1.8 下注意 PermGen 已改为 Metaspace,所以这两个参数在新版本里可能不生效,只调堆大小即可。不建议一开始就调很大,256M 到 512M 足够一个课程设计级别项目跑得很顺。
4. 前端的双轨写法:JSP 与 Vue 如何在挂号流程里协同
4.1 JSP 负责服务端渲染与表单提交
这套项目用的是 JSP + Vue 组合,很多人第一次看到会觉得奇怪:JSP 是服务端模板技术,Vue 是前端 JavaScript 框架,两者能不能混用?实际上在 SSM 项目里它们承担着不同职责:JSP 负责把后端传来的数据渲染成 HTML,并且把 JSP 自带的一些标签库(比如c:forEach)用来循环输出科室列表、医生列表;Vue 则负责页面上更细腻的动态交互,比如搜索时实时过滤、表单提交前的前端校验、按钮点击后局部刷新。
挂号页面常见的写法是:后端 Controller 返回一个包含科室列表和医生列表的 ModelAndView,JSP 里用 EL 表达式把这些数据输出成表格或下拉框。一个典型的 JSP 片段长这样:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head><title>门诊挂号</title></head> <body> <h3>选择科室</h3> <select id="departmentSelect"> <c:forEach items="${departmentList}" var="dept"> <option value="${dept.id}">${dept.name}</option> </c:forEach> </select> </body> </html>${departmentList}是 Controller 里放进 Model 的数据,items指定要循环的集合,var定义循环变量dept。JSTL 的forEach循环和 Java 的 for-each 几乎一一对应,它在服务器端执行完后输出纯 HTML 给浏览器,所以页面里看到的是渲染好的<option>标签,源码里则是 JSP 标签。这种方式的优点是首屏加载快,数据直接输出在页面里,不用额外发起 AJAX 请求。
4.2 Vue 嵌入 JSP:局部刷新与表单校验
Vue 在这套项目里的价值更多体现在「交互增强」层面。最典型的是挂号前选择医生的场景,用户选中科室后,医生列表应该异步刷新,而不是刷新整个页面。实现方法是页面上引入 Vue 的 CDN 文件,然后用 Vue 的data和methods管理当前选中的科室 ID、医生列表等状态。Vue 把数据绑定和 DOM 更新做了封装,写起来比手工操作 jQuery 方便得多。
// 在 JSP 页面底部或独立 js 文件中 var vm = new Vue({ el: '#app', data: { currentDeptId: '', doctorList: [], selectedDoctorId: '' }, methods: { // 根据当前科室加载医生列表 loadDoctors: function () { var self = this; $.ajax({ url: '/hospital/doctor/listByDept', type: 'POST', data: { deptId: self.currentDeptId }, dataType: 'json', success: function (result) { if (result.code === 0) { self.doctorList = result.data; } } }); } } });el: '#app'表示 Vue 接管页面上id="app"这个 DOM 节点,data里声明的变量会被响应式地绑定,methods里的loadDoctors在用户切换科室时被触发调用。$.ajax是 jQuery 的请求方法,项目里通常会同时引入 jQuery。这个组合的本质是:JSP 负责页面骨架和首屏数据,Vue 负责数据变化后的视图更新,两个框架通过 AJAX 接口完成数据交换,互不冲突。
4.3 挂号主流程的前后端协作边界
前端看起来是一个连环表单,后端其实要处理三个步骤:选科室、选医生、提交挂号。前两步可以通过 AJAX 动态加载数据,最后一步是真正的业务动作,必须交给 Controller 处理并走数据库事务。这里常见的一个错误是前端把「余号判断」作为唯一校验,用户看到还有号就允许提交,结果后端没有做二次校验,造成超挂。
正确做法是后端在registration插入前先做数量判断,并保证判断和插入在同一个事务里。代码示意大概是这样:
@Service public class RegistrationService { @Transactional(rollbackFor = Exception.class) public boolean createRegistration(Registration reg) { // 1. 查询医生当日已挂号人数 // 2. 和号源总数对比 // 3. 数量足够才执行 insert // 4. 返回操作结果 } }@Transactional注解是 Spring 的事务开关,rollbackFor = Exception.class表示只要方法内抛出运行时异常,整个操作就回滚。挂号场景最怕的就是第一步判断通过后、第三步插入失败,导致号被多放出去或数据不一致。事务的意义就是让这两个步骤要么都成功,要么都失败。前端做校验是提升体验,后端做事务校验才是保证数据正确和安全的基础。
4.4 不要在 JSP 里堆大段 JS:代码组织建议
从源码包的命名习惯来看,JSP 页面里直接嵌入一段 JS 很正常,但如果你要做二次开发,建议把大段逻辑抽到独立的.js文件里。比如挂号页面的 Vue 实例、AJAX 请求方法、表单提交逻辑,全部抽到js/register.js中,JSP 页面只需在底部引入。这样做的好处是:跨页面复用同一套逻辑时不用复制粘贴多份;修改接口返回结构时只需要动一个文件。
<!-- 抽离到独立 js 文件后,在 JSP 底部引入 --> <script src="${pageContext.request.contextPath}/js/register.js"></script>${pageContext.request.contextPath}是 JSP 里获取项目根路径的标准写法,它的值是/hospital这样的上下文路径,加上它以后 JS 文件的引用就不会因为路径层级嵌套而 404。文件抽离后调试时直接在浏览器开发者工具的 Sources 面板里给register.js打断点即可,不用再去 JSP 源码里找那几行<script>。这也是把「毕设代码」改造成「工程化代码」的关键一步。
5. 部署与运行避坑:五个让 SSM 项目直接翻车的问题
5.1 中文乱码:页面全是问号的根因
现象:启动登录后,页面上的中文(科室名、用户姓名)全部显示为???或乱码,但英文和数字完全正常。
原因:三层链路中至少一处字符集不统一。最常见的是数据库表字段是latin1编码,而 Java 代码写入的是 UTF-8;或者 JSP 页面没有声明contentType;也可能是 MySQL 连接 URL 里没带characterEncoding=utf8。
解决:先查数据库端再查代码端。用SHOW CREATE TABLE department;看表字符集,如果是latin1,执行ALTER TABLE department CONVERT TO CHARACTER SET utf8mb4;。同时确认 JSP 第一行有<%@ page contentType="text/html;charset=UTF-8" language="java" %>,并检查连接 URL 是否带上了characterEncoding=utf8。这三处对齐后,乱码基本能解决。
5.2 启动报 ClassNotFoundException:com.mysql.jdbc.Driver 找不到
现象:Tomcat 启动后控制台报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver,或者运行时报NoClassDefFoundError找不到驱动类。
原因:MySQL 驱动 Jar 包没有被打包进WEB-INF/lib目录。很多 Spring 工程在 IDEA 里依赖能解析,但发布到 Tomcat 时依赖未同步进 Artifact,尤其是不用 Maven、手动管理 Jar 包的项目更容易出这个问题。
解决:在 IDEA 里打开Project Structure -> Artifacts -> Output Layout,检查WEB-INF/lib下是否有mysql-connector-java的 Jar。如果没有,点击加号把外部库添加进去;如果用的是 Maven,确认 pom.xml 中依赖没有设置scope=provided,否则打包时会排除它。常见驱动版本限制不多,与 MySQL 5.7 配套建议用mysql-connector-java-5.1.47或相近版本。
5.3 登录后跳到 404:Context Path 对不上
现象:登录页能打开,但提交用户名密码后浏览器地址变成http://localhost:8080/loginPage之类的路径,直接 404。
原因:JSP 页面或 JS 代码里写的请求 URL 是绝对路径,比如 URL 写的是/user/login,而项目 Context 是/hospital,实际请求地址应该是/hospital/user/login,少了前缀自然 404。
解决:在 JSP 里用${pageContext.request.contextPath}拼接路径基准,或者在<form>标签的action属性里写${pageContext.request.contextPath}/login。另外顺手检查 Tomcat 的server.xml里 Host 的appBase和 Context 配置,确保应用发布名和代码里写的路径一致。
5.4 控制台报错:Unknown system variable 'time_zone'
现象:首页加载时控制台抛出java.sql.SQLException: Unknown system variable 'time_zone',页面直接 500。
原因:这个报错在 MySQL 5.7 连接时出现,基本可以断定是 Connector/J 驱动版本过新(8.x),而服务器是 MySQL 5.7,驱动要求连接参数里带serverTimezone,或者驱动和数据库版本不匹配,导致系统变量无法识别。
解决:优先把驱动替换为mysql-connector-java-5.1.x版本,如果必须用新版驱动,则在连接 URL 上追加serverTimezone=Asia/Shanghai参数,完整示例:
jdbc.url=jdbc:mysql://localhost:3306/hospital?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/ShanghaiserverTimezone指定了数据库时区,旧版驱动不传这个参数也能走,新版驱动因为引入了时区检测所以必须显式声明。这个报错卡住不少初次用新版驱动跑老项目的人,看到time_zone关键字直接按这个方向排查即可。
5.5 请求方法不支持:GET/POST 不匹配导致 405
现象:点击「保存挂号」按钮后,页面提示HTTP 405 - Method Not Allowed。按钮逻辑明明没错,但请求就是进不去 Controller。
原因:SpringMVC 的@RequestMapping注解里指定了method = RequestMethod.GET,而前端表单用的提交方式是 POST,导致匹配不到处理方法。更常见的是写死在@RequestMapping里只允许 POST,但页面用window.location.href跳转,这种跳转都是 GET 请求。
解决:在@RequestMapping上要不就同时写method = {RequestMethod.GET, RequestMethod.POST}支持两种方式,要不就改成@GetMapping/@PostMapping并检查前端提交方式是否匹配。给一个同时兼容 GET 和 POST 的写法:
@RequestMapping(value = "/registration/save", method = {RequestMethod.GET, RequestMethod.POST}) public String save(Registration reg) { return "redirect:/registration/list"; }method数组里同时声明 GET 和 POST,可以减少前后端匹配失误的概率。这个方法字段是排查 405 的关键入口,遇到此类报错先不要看前端逻辑,直接看 Controller 的映射声明最省事。
6. 让这个项目变成你的作品:三个验证点与扩展方向
从「能跑通」到「是自己的项目」,中间隔着三个验证门槛。第一是数据验证:在挂号单列表里看到一条真实记录,并且手动改数据库里的状态字段,再到页面上刷新确认显示同步变化,这能证明项目的数据链路是通的。第二是事务验证:故意在createRegistration方法里制造一个空指针异常,看已插入的挂号记录是否回滚,回滚说明@Transactional生效,不回滚说明事务配置白写了。第三是权限验证:用普通用户账号去访问管理员的 Action 地址,如果系统直接放行,那你需要补一个拦截器或 HandlerInterceptor 来自行加固——这本身就是很好的论文创新点。
扩展方向里我比较推荐两个:第一个是把图片上传加进挂号凭证或者医生头像展示,这里就涉及「jsp 图片如何对坐标定位」的实际需求,常见做法是图片上传后以隐藏表单项保存 x/y 坐标,再把图片路径存进数据库,JSP 端用background-position实现局部标注;第二个是给挂号记录增加导出 Excel 功能,用 POI 生成 xlsx 后通过响应流输出下载。这两个方向改动范围可控,又能在答辩时讲出完整的设计思路。我曾经带过一个学弟跑这套系统,他图省事跳过了事务验证这步,结果答辩现场演示取消挂号的时时候据库里的号源被多放出去都毫不知情,最后只能现场开着 SQL 改数据圆场。从那以后我每次拿到新的 SSM 项目,都会强制走一遍「插入-回滚-验证」全流程,确认事务是真的有效再去做扩展开发。希望帮到你。
本文还有配套的精品资源,点击获取