资讯动态

Spring Boot乡村养老管理系统源码解析:从数据库设计到二次开发

发布时间:2026/10/20 13:34:09 来源:尧图企业网站定制
简介一套基于Spring Boot框架构建的乡村养老服务管理系统源码面向计算机相关专业学习者、毕业设计及农村养老信息化项目开发者。系统覆盖管理员、老人、医疗人员、乡村志愿者四类角色包含账户管理、服务申请与记录、健康信息维护、志愿活动参与及系统数据管理等功能模块适合用做课程设计、毕业设计或实际项目参考。压缩包共926个文件体积33.73MB以java、vue、js、html、css等为主同时包含sql数据库脚本、yml配置、bat启动脚本及若干图片资源方便直接导入开发环境运行与二次开发。目前已有43人浏览学习可用性与内容质量已获得初步认可。通过该项目可掌握Spring Boot与Vue前后端分离开发、角色权限管理、数据表设计及乡村场景下的业务建模方法是一份完整度较高的实战资源。1. 乡村养老管理系统Spring Boot 源码到底能给你什么如果你接手过乡镇或街道的养老台账工作大概率经历过这样的场景老人信息登记在本子上走访记录拍成照片存在手机里补贴发放靠 Excel 来回传年底汇总时翻箱倒柜对不上数。这个基于 Spring Boot 框架的乡村养老服务管理系统本质就是把这些分散的养老业务——老人档案、日常走访、健康记录、补贴发放、护工排班——收拢到一个后台里用一套标准的增删改查和审批流程替代手工台账。它适合两类人一类是乡镇/村级负责养老业务的工作人员需要一套能直接部署、能录入真实数据的内部系统另一类是刚学完 Spring Boot 想做项目练手的学生或转行者这套源码的模块划分和业务字段设计比网上的商城类 Demo 更贴近真实业务场景。这里先说清楚拿到源码不是双击就能跑你需要本地有 JDK、Maven 和 MySQL然后按下面这几章的思路先拆结构、再建库、后调接口、最后部署每一步都会遇到具体的坑我会把我踩过的和帮别人排过的都写出来。2. 拆解源码结构Spring Boot 项目是怎么组织养老业务的拿到压缩包先别急着启动花十分钟把目录结构过一遍能省掉后面大半的排查时间。这套系统的代码分层是典型的 Spring Boot 单体应用结构业务模块围绕着“老人”和“服务”两条主线展开整体清晰度取决于作者对职责边界的把控。2.1 源码包里的标准目录controller、service、mapper 各管什么事解压后你会看到src/main/java下按技术分层分包常见做法是按controller / service / mapper或 dao/ entity / config五层划分。以这套乡村养老系统为例controller里放的是接收前端请求的入口类比如ElderController、VisitController、SubsidyController每个类对应一个业务域service层写具体业务逻辑比如“新增老人时要校验身份证号是否重复”“提交补贴申请时要检查该老人是否已有未审批的单子”mapper层负责和数据库打交道一般配合 MyBatis 的 XML 文件或注解使用entity里是数据库表对应的实体类config放配置类比如跨域配置、拦截器配置、分页插件配置。src/main/java/com/xxx/ruralelder/ ├── controller/ # 接口入口 ├── service/ # 业务逻辑 │ └── impl/ ├── mapper/ # 数据访问层 ├── entity/ # 数据库实体 ├── config/ # 配置类 └── RuralElderApplication.java # 启动类先打开启动类RuralElderApplication.java确认SpringBootApplication注解存在并且MapperScan指向了正确的 mapper 包路径。这一点是新手最容易翻车的地方——如果MapperScan漏写或者写错包名启动时会报mapper bean 找不到的错误而且错误信息往往在启动最后阶段才抛出来看起来很像是数据库连接问题实际却是扫描路径不对。2.2 application.yml 里的关键配置数据源、端口、MyBatis核心配置文件在src/main/resources/application.yml也可能是.properties后缀这是项目跑起来的命门。以这套系统常见配置为模板你需要重点确认这几项server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/rural_elder?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 mybatis-plus: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.xxx.ruralelder.entity configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl pagehelper: helper-dialect: mysql reasonable: true这里说三个最容易踩的配置点。第一个是serverTimezone如果你是本地 Windows MySQL 8.x 的组合连接串里不带serverTimezoneAsia/Shanghai大概率启动直接报Communications link failure或者时区异常。第二个是map-underscore-to-camel-case数据库字段习惯用下划线如id_cardJava 实体用驼峰如idCard这行配置打开后 MyBatis 自动做映射不打开的结果是接口能通但查出来的对象所有字段都是 null这种问题光看日志很难定位。第三个是log-impl配置把 MyBatis 的 SQL 日志打印到控制台开发阶段强烈建议开着它能让你直接看到每次请求实际执行的 SQL 语句——排查“接口返回数据和预期不符”时先看 SQL 是不是查错了表。2.3 启动项目的第一步本地环境确认与最小启动命令环境检查顺序我一般这样走先确认java -versionSpring Boot 2.x 要求 JDK 8Spring Boot 3.x 要求 JDK 17源码里如果是 2.x 就别强行用 Java 21 跑会有兼容问题再确认mvn -v可用最后确认 MySQL 服务已启动且能连上。数据库方面源码里通常会附带sql文件夹存放建库脚本你要做的是先创建数据库再导入脚本# 1. 进入 MySQL创建数据库并指定字符集 mysql -u root -p -e CREATE DATABASE IF NOT EXISTS rural_elder DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 2. 导入源码附带的 SQL 脚本 mysql -u root -p rural_elder sql/rural_elder.sql # 3. 启动项目在源码根目录执行 mvn spring-boot:run启动过程中盯着日志看两个关键点一是Tomcat started on port 8080出现表示 Web 容器起来了二是 MyBatis 的 mapper 有没有报Invalid bound statement这个错误通常意味着application.yml里的mapper-locations路径写错或者 XML 文件的 namespace 和 Mapper 接口全限定名不一致。启动成功后浏览器访问http://localhost:8080/看到登录页或接口返回 JSON第一步就算跑通了。3. 数据库设计拆解养老业务的核心表和字段怎么规划乡村养老服务管理系统和普通后台管理系统最大的区别在数据模型上。它不只是简单的“用户-角色”表结构还牵扯到老人档案、走访记录、健康数据、补贴发放、护工排班等民生业务字段设计直接影响后续功能开发的顺手程度。3.1 六张核心业务表从老人档案到补贴审批我先用一张表把这套系统中常见的核心表和它们之间的关系理清楚你在源码的sql目录里大概率能找到对应的建表语句。表名业务含义关键字段关联关系elder_info老人基础档案id_card、birth_date、contact_phone、health_status其他业务表都通过elder_id关联它visit_record走访记录visit_date、visit_type、content、next_visit_dateelder_id指向老人health_record健康档案blood_pressure、blood_sugar、medication_info、record_dateelder_id指向老人subsidy_apply补贴申请与审批subsidy_type、amount、apply_date、approve_statuselder_id指向老人nurse_info护工信息name、phone、shift_type、service_village一对多关联到老人服务sys_user系统登录账号username、password加密存储、role_type角色区分管理员/村委/护工这张表里有几个字段是养老业务特有的坑我单独拉出来说。第一个是id_card身份证号。老人信息录入时身份证号是唯一标识但乡村场景下经常出现“身份证号缺失”的情况——高龄老人没有二代身份证或者子女代办时记错号码。常见做法是在该字段上建唯一索引但不设置非空约束允许为空但保证不为空的记录不能重复。第二个是health_status健康状态字段通常用枚举值表示比如 1-自理、2-半失能、3-失能不要直接存汉字否则后续做统计报表时GROUP BY出来的结果很不好处理。第三个是amount补贴金额必须用DECIMAL(10,2)不要用FLOAT或DOUBLE涉及钱的数据用浮点数存储会出现精度误差比如实发 300.00 元算出来却是 299.9999 元。3.2 看建表脚本关注索引设计和状态字段的默认值源码的 SQL 脚本里你重点看三处。一是看有没有UNIQUE KEY特别是elder_info.id_card和sys_user.username这两个字段唯一索引是防止重复数据的最后一道防线如果脚本里没有自己在 Navicat 或命令行里补上。二是看approve_status这类审批状态字段的默认值正常设计应该是DEFAULT 00-待审批、1-已通过、2-已驳回如果作者写成了允许 NULL那查询“所有待审批的补贴单”时要把IS NULL的情况也考虑进去容易出漏数据。三是看字段注释靠谱的脚本每列都有COMMENT说明如果一个表的字段注释大量缺失说明这个项目可能是半成品二次开发前需要找作者确认字段含义。CREATE TABLE subsidy_apply ( id BIGINT NOT NULL AUTO_INCREMENT, elder_id BIGINT NOT NULL COMMENT 老人ID关联elder_info表, subsidy_type VARCHAR(50) NOT NULL DEFAULT living_allowance COMMENT 补贴类型living_allowance-生活补贴medical_aid-医疗救助, amount DECIMAL(10,2) NOT NULL COMMENT 补贴金额元, apply_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 申请日期, approve_status TINYINT NOT NULL DEFAULT 0 COMMENT 审批状态0-待审批1-已通过2-已驳回, approve_remark VARCHAR(255) DEFAULT NULL COMMENT 审批意见, approve_time DATETIME DEFAULT NULL COMMENT 审批时间, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_elder_id (elder_id), KEY idx_approve_status (approve_status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT养老补贴申请审批表;注意这个表设计里有一个很关键的查询场景乡镇管理员每个月要导出“本月待发放补贴名单”最常见的过滤条件就是approve_status 0加日期范围所以索引要建在approve_status和apply_date上而不是单独建在elder_id上。idx_elder_id是给“查某个老人的所有补贴申请”用的两者业务场景不同索引设计不能只图省事。3.3 设计层面最重要的一个原则别过度建物理外键我刚接触这类业务系统时喜欢在每个表上把FOREIGN KEY都建上觉得这样数据安全后来发现是给自己挖坑。乡村养老系统有一个高频场景是“批量导入老人数据”用 Excel 或 CSV 一次性导入几千条记录物理外键会导致导入必须严格按表顺序执行而且报错信息不直观——明明是一条数据格式不对却报外键约束失败排查成本很高这是典型的过度约束。这里有个关键取舍要说明保证关联数据完整性靠的应该是服务层代码里的逻辑校验而不是靠数据库物理外键。源码里如果看到表结构里有CONSTRAINT FOREIGN KEY语句建议你在二次开发时删掉它改用逻辑外键——也就是只在子表存elder_id字段不建物理约束查询时通过JOIN或子查询关联。这样做的代价是需要自己在删除老人时手动确认有没有关联的走访记录和补贴单好处是批量导入、批量更新时不会被数据库的约束机制打断。我见过不止一次因为物理外键导致“删一个老人要连带处理五张表”的尴尬局面这个原则越早想明白越省事。4. 核心接口与业务闭环从新增老人到补贴审批的实现路径结构拆完、库建好了接下来看代码实现。看 Spring Boot 源码项目不要按文件顺序从头看到尾要按“一条业务链路”看——从 Controller 入口进到 Service 业务逻辑再到 Mapper 的 SQL完整走一遍你就知道这套系统是怎么跑起来的。4.1 老人档案新增核心接口的代码链路先看ElderController这是老人档案模块的入口。常见的写法是RestControllerRequestMapping(/api/elder)新增接口用PostMapping。代码大概是这个结构RestController RequestMapping(/api/elder) public class ElderController { Autowired private ElderService elderService; PostMapping(/add) public ResultString addElder(RequestBody Validated ElderInfo elder) { elderService.addElder(elder); return Result.success(新增成功); } }Result是统一返回体一般包含code、message、data三个字段。这套系统比较好的设计是所有的接口返回值都用Result包装而不是直接返回实体对象好处是前端统一处理错误状态不用每个请求单独判断异常情况。如果你看到源码里有接口直接返回了实体类那就是偷懒写法二次开发时不要学。接着看ElderServiceImpl里的实现逻辑。业务层至少要做三件事缺一不可。第一是身份证号去重查询数据库里有没有相同的id_card记录有则抛出业务异常第二是填充默认值比如health_status如果前端没传就默认 1自理、status默认 0正常第三是记录创建时间created_at字段如果数据库有默认值可以不加但如果你在代码里统一设置维护起来更清晰。Service public class ElderServiceImpl implements ElderService { Autowired private ElderMapper elderMapper; Override Transactional(rollbackFor Exception.class) public void addElder(ElderInfo elder) { // 1. 身份证号去重允许为空但不可重复 if (StringUtils.isNotBlank(elder.getIdCard())) { Integer count elderMapper.countByIdCard(elder.getIdCard()); if (count 0) { throw new BusinessException(身份证号已存在请勿重复录入); } } // 2. 设置默认值 if (elder.getHealthStatus() null) { elder.setHealthStatus(1); } // 3. 入库 elderMapper.insert(elder); } }注意Transactional(rollbackFor Exception.class)这行。很多新手写事务只写Transactional但 Spring 默认只在遇到RuntimeException时回滚如果业务层抛出的是自定义异常且不是运行时异常事务不会回滚——数据库里可能已经插入了一条半成品数据。rollbackFor Exception.class的意思是所有异常都触发回滚在养老系统的“新增老人-创建档案-生成唯一编号”这种多步骤操作里必须这么写。4.2 走访记录分页查询前端表格数据怎么高效加载走访记录是乡村养老系统里数据量增长最快的表——每位老人每月至少一条走访记录一个街道几千位老人一年就有几万条数据。接口如果一次性全查出来前端表格直接卡死所以分页是刚需。GetMapping(/visit/page) public ResultPageResultVisitRecord pageVisit( RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) Long elderId, RequestParam(required false) String visitType) { PageHelper.startPage(pageNum, pageSize); ListVisitRecord records visitMapper.selectByCondition(elderId, visitType); PageInfoVisitRecord pageInfo new PageInfo(records); return Result.success(PageResult.from(pageInfo)); }这套系统如果用了 PageHelper关键点是PageHelper.startPage之后必须紧跟第一条查询语句中间不能插入其他数据库操作——这是 PageHelper 的底层机制决定的它是通过拦截器在下一条 SQL 上自动拼接LIMIT如果在 startPage 和查询之间执行了别的 SQL分页就会加错地方导致查出来的数据张冠李戴这是很经典的一个坑。selectByCondition对应的 Mapper XML 里if标签做动态 SQL 拼接是 MyBatis 最常用的写法select idselectByCondition resultTypecom.xxx.ruralelder.entity.VisitRecord SELECT * FROM visit_record where if testelderId ! null AND elder_id #{elderId} /if if testvisitType ! null and visitType ! AND visit_type #{visitType} /if /where ORDER BY visit_date DESC /selectwhere标签会自动去掉开头的AND这是 MyBatis 内置的功能比手动写WHERE 11干净得多。你检查源码时如果看到WHERE 11说明是早期写法不影响功能但不够优雅。另外注意ORDER BY visit_date DESC必须写在分页 SQL 里实现“最新的走访记录排最前面”这个业务诉求如果排序字段和分页拼接的顺序不对会出现“翻页数据然后重新排序导致重复记录”的诡异现象排查起来非常耗时间。4.3 补贴审批状态机如何避免“重复审批”和“状态回退”补贴审批是养老系统里最能体现“设计水平”的一个功能。从流程上讲一条补贴单要经历“待审批 → 已通过/已驳回”的状态变化。但实际业务里有个高频场景乡镇管理员和县级管理员同时打开同一个审批单一个点了通过另一个又点了驳回。如果代码里没做状态校验后续的数据报表就会同时出现“通过”和“驳回”两个版本这就是状态一致性被破坏了。Override Transactional(rollbackFor Exception.class) public void approveSubsidy(Long subsidyId, Integer approveStatus, String remark) { // 1. 查询当前状态 SubsidyApply apply subsidyMapper.selectById(subsidyId); if (apply null) { throw new BusinessException(补贴申请单不存在); } // 2. 检查状态是否合法只有待审批的单子才能走审批 if (apply.getApproveStatus() ! 0) { throw new BusinessException(该申请单已审批请勿重复操作); } // 3. 更新状态 SubsidyApply update new SubsidyApply(); update.setId(subsidyId); update.setApproveStatus(approveStatus); update.setApproveRemark(remark); update.setApproveTime(new Date()); subsidyMapper.updateById(update); }这里有个判断只靠 Java 代码判断approveStatus ! 0就抛异常在“单机单库”场景下基本够用但如果你要更严密的控制应该在数据库层面加乐观锁也就是给subsidy_apply表加一个version字段修改前先查version更新时SET version version 1 WHERE version #{oldVersion}如果影响行数为 0 说明被别人改过了。代码里用 MyBatis-Plus 的Version注解是最省事的方案但要注意必须注册乐观锁插件才生效不是加个注解就完事。对于这套系统的应用场景先做好 Java 层的状态校验业务上已经足够乐观锁属于锦上添花。审批通过这一环牵扯出一个容易忽略的需求审批通过后要不要自动生成“发放记录”常见做法是单独建一张subsidy_pay表审批通过时插入一条待发放记录。如果你在源码里没有看到这张表说明系统只做到了“审批”这一步发放确认功能需要二次开发自己补这也是很多人拿到源码后觉得“少了点什么”的原因它不一定是对应网络上某个具体版本的完整功能需要自己判断是否要补全。5. 避坑指南启动报错、查询异常和审批状态错乱代码看明白后就该亲自动手跑一跑了。这一章内容全部来自实际运行经验你按照前一章的流程操作大概率会在某些环节踩到一模一样的坑。我按“启动阶段-运行阶段-业务阶段”的顺序列出最高频的五个问题每个都按“现象-原因-解决”写。5.1 时区问题数据库查出来的时间比本地慢了 8 小时现象启动项目后打开走访记录列表发现每条记录的visit_date都比实际录入时间慢了 8 小时。如果是 PostgreSQL 或 MySQL 8.x默认时区往往不是东八区JDBC 连接如果没有显式指定时区取出来的时间就是 UTC 时间转成中国时间自然慢 8 小时。原因application.yml的数据库连接 URL 里没有加serverTimezoneAsia/ShanghaiMySQL 驱动使用默认时区解析日期时间。这个现象在本地开发时特别容易忽略因为系统刚启动时你看到的可能是“空记录”而不是“错时间”等录一条测试数据进去才发现不对。解决在 jdbc url 上显式加上参数。url: jdbc:mysql://localhost:3306/rural_elder?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai改完配置文件后重启项目再录一条数据验证。这里有个提示serverTimezone参数是 MySQL Connector/J 8.x 版本的必填项如果用 5.x 的驱动不填也能跑但既然源码是基于较新框架的建议驱动版本跟随 MySQL 8.x避免两种版本之间的行为差异变成隐藏雷区。5.2 MyBatis 查询出的对象所有字段都是 null现象接口返回的 JSON 结构正常code是 200但data里的实体对象每个字段都是 null或者只有主键 id 有值。原因重点检查两点。一是数据库字段和实体属性映射不上最典型的就是数据库id_card没能映射到实体的idCard二是 XML 里的resultType写成了java.util.Map而实际返回的是一个复杂对象字段名对不上导致反序列化失败。解决先确认application.yml里map-underscore-to-camel-case: true配了没有——配了还 null就去看 Mapper XML 的resultMap是不是手动指定了映射关系并且写漏了字段。还有一种隐蔽情况是实体类里字段名写错比如把phone写成了mobile编译不报错但 SQL 里查出的phone列没人接收结果也是 null。!-- 排查时优先看这里 -- resultMap idElderResultMap typecom.xxx.ruralelder.entity.ElderInfo id columnid propertyid/ result columnid_card propertyidCard/ result columnhealth_status propertyhealthStatus/ /resultMap如果你发现源码里的resultMap缺少字段就直接加一行result标签然后重启验证。这个问题在加了聚合函数或JOIN查询时更容易冒出来因为查出来的列名不再是实体类默认对应的那张表的列名要格外留意。5.3 新增补贴申请后审批列表查不到这条记录现象前端提交补贴申请提示成功但在审批列表里翻不到这条单子数据库里subsidy_apply表里也没有新数据或者有数据但approve_status是 NULL。原因两种可能。一是事务没提交——addSubsidy方法上没加Transactional应用在方法中途抛了异常数据库自动回滚但前端没有收到明确的错误反馈二是实体里approveStatus是基本类型int默认值是 0插入时 MyBatis 把这个 0 覆盖了数据库字段的DEFAULT 0但如果实体类型是Integer且没赋值插入的就是 NULL查询时approve_status 0过滤不到这条数据。解决在SubsidyApply实体类里把approveStatus定义为Integer并且在插入前显式setApproveStatus(0)在代码里设置初始值更保险。然后确认addSubsidy方法上有Transactional(rollbackFor Exception.class)。还有一个排查小技巧打开 MyBatis 的 SQL 日志看 insert 语句实际执行时approve_status这一列传入的值是什么——如果是 NULL那就和数据库默认值无关问题出在代码层。5.4 分页数据出现重复或缺失现象走访记录列表总共 30 条数据每页 10 条但第二页出现了一条第一页已经展示过的记录或者第二页的数据在顺序上跳跃了。原因查了ORDER BY——如果排序字段是visit_date而多个记录的visit_date是同一秒MySQL 在分页时返回的顺序就不稳定不同页之间很可能出现同一批次的数据被重复或漏掉。这个现象在 MySQL 8.x 上尤其明显因为它默认的优化器可能选择不同的执行计划。解决在排序字段后面加一个“绝对唯一”的排序条件。ORDER BY visit_date DESC, id DESCid是主键保证了同一天内多条记录的排序是确定的这样分页才能做到不重不漏。这是一个很多人容易忽略的细节但它直接影响报表数据的准确性尤其是在导出 Excel 逐页处理时重复数据会导致计数错误。5.5 权限控制形同虚设普通用户能直接调用管理员接口现象前端页面通过隐藏按钮做了“权限控制”但直接调用后端接口 URL普通账号也能访问管理员的接口比如直接访问/api/subsidy/approve把一条补贴单审批通过。原因这套系统的权限校验只做在了前端展示层后端Controller上没有加任何拦截器或注解校验。Spring Boot 项目里如果没引入 Spring Security 或 Shiro也没有自定义 HandlerInterceptor那么所有接口默认都是匿名可访问的。解决简单可靠的方案是加一个自定义拦截器HandlerInterceptor里校验token对应的用户角色。常见做法是在登录成功后生成一个 token 放进 Redis拦截器里校验请求头里的 token 并查询用户角色用RequestMapping路径做匹配比如/api/subsidy/**只允许role_type 1管理员访问。public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(token); // 校验 token 并查询用户信息这里省略具体逻辑 if (token null || .equals(token)) { response.setStatus(401); return false; } return true; } }这是最容易拖垮整个系统安全性的一个坑关系到是否值得把真实数据放进去。如果你拿源码只做课程设计、演示 Demo不部署到公网环境影响会小一些但如果要在单位局域网里正式使用后端权限校验是必须补的而且建议从一开始就对接到登录状态不要临时加。6. 二次开发的最佳起点加一个“紧急联系人”字段的完整链路前面把系统的结构和核心链路都过了一遍最后落地在一个具体的二次开发任务上给老人档案表加一个“紧急联系人及电话”字段。这是最典型、也最能检验你掌握程度的小改动因为它要动实体、数据库、Mapper XML、前端表单四个地方链路完整但工作量小适合作为上手的第一个练习。第一步改数据库。给elder_info表加两个字段emergency_contact和emergency_phone直接在 Navicat 里修改表结构或执行下面的 SQLALTER TABLE elder_info ADD COLUMN emergency_contact VARCHAR(50) DEFAULT NULL COMMENT 紧急联系人, ADD COLUMN emergency_phone VARCHAR(20) DEFAULT NULL COMMENT 紧急联系电话;第二步改实体类在ElderInfo.java里加两个属性注意字段名要和数据库列名对应开启了驼峰映射后emergencyContact自动对emergency_contactprivate String emergencyContact; private String emergencyPhone;第三步看ElderMapper.xml的 insert 语句把新字段加进去。这里特别提醒MyBatis-Plus 如果用的insert(entity)自动生成 SQL 就不用改 XML但如果你这套源码的 insert 是手写在 XML 里的必须手动加列名和#{emergencyContact}占位符漏掉的话数据库字段加上了但插入时新字段始终是 NULL。insert idinsert parameterTypecom.xxx.ruralelder.entity.ElderInfo INSERT INTO elder_info (elder_name, id_card, health_status, emergency_contact, emergency_phone) VALUES (#{elderName}, #{idCard}, #{healthStatus}, #{emergencyContact}, #{emergencyPhone}) /insert第四步改前端表单找到老人新增/编辑页面加两个输入框绑定对应的字段名。这里用 Vue 的话就是在表单 model 里加emergencyContact和emergencyPhone然后表单提交时自动会带上。改完这四处重启项目、录入一条带联系人的老人数据再查数据库确认字段有值这个二次开发就完成了。整个过程走下来你对这套源码的掌控程度会比单纯看一遍代码高出很多。我每次拿到一份新系统源码都会找一个“加字段”的任务练手两小时就能摸清一个项目的骨架和风格。希望这篇笔记能帮你在乡村养老服务管理系统这个方向上少踩几个坑顺利把源码跑起来改起来。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑