news 2026/10/7 5:39:21

基于JAVA的宠物管理系统:从数据库设计到核心功能落地

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于JAVA的宠物管理系统:从数据库设计到核心功能落地

简介:这是一套面向高校计算机相关专业学生与Java初学者整理的宠物管理系统毕业设计完整资料,围绕宠物网站的设计与实现展开,适合需要完成课程设计、毕业设计或希望以真实项目练手Java Web开发的学习者。压缩包共14个文件,约132.62MB,包含4个mp4项目辅导视频、3个doc论文与任务书文档、1个pptx答辩演示、1个sql数据库脚本、1个zip源码包以及png界面截图和说明txt,覆盖从部署到功能演示的完整链路。系统分为前台与后台两大模块:前台支持用户登录注册、商品查找与类别导航,后台由管理员完成订单、商品、公告、会员、用户及个人信息维护等操作,并对核心数据表结构做了详细说明。视频按数据库创建与项目运行、前台模块、后台商品用户模块、系统模块分节讲解,便于对照源码理解实现思路。目前已有267人学习,可作为毕业设计选题与Java Web实战的参考方案。

1. 宠物管理系统到底在管什么:从一张寄养单说起

宠物医院前台最怕的不是忙,是乱。一只金毛寄养三天,主人临时加一次驱虫,中间换了粮,出院时还要补打一针疫苗——这些信息如果散落在纸质登记本、微信聊天记录和前台脑子里,月底对账一定翻车。基于 JAVA 的宠物管理系统要解决的,就是把「宠物档案、主人信息、寄养/诊疗记录、疫苗驱虫提醒、费用结算」这几件事收进一个数据库,让每一次操作都有迹可循。它适合两类人:一是计算机专业做课程设计或毕业设计的学生,需要一套能跑通、能讲清楚、能写进论文的完整项目;二是刚接手小型宠物店或诊所信息化的小团队,想用一套可控的源码改出自己的业务逻辑。JAVA 在这里的价值不是「因为学校教这个」,而是生态成熟、数据库连接稳定、后期加权限和报表都方便。下面按「先跑起来、再改得动、最后讲得清」的顺序拆开讲。

2. 技术选型与数据库设计:为什么是 Spring Boot + MyBatis + MySQL

2.1 三层架构不是摆设,它决定了你改需求时改哪一层

常见做法是 Controller 接请求、Service 写业务规则、Mapper 管数据库读写。宠物管理系统的业务规则其实不少:寄养按天计费、疫苗到期提前提醒、同一主人名下多只宠物要能一起查。如果把这些逻辑全塞进 Controller,后面加一个「会员折扣」就要翻遍所有接口。分层之后,改计费规则只动 Service,改字段只动 Mapper 和实体类。

实体类建议至少这几张表:owner(主人)、pet(宠物)、boarding(寄养记录)、medical_record(诊疗记录)、vaccine(疫苗记录)、bill(账单)。表之间用外键或逻辑外键关联,宠物表里放owner_id,寄养表里放pet_id。这里有个血泪经验:不要用宠物名做关联字段,重名太常见,一定要用自增主键或业务编号。

2.2 建库建表的最小 SQL 与字段说明

下面这段 SQL 可以直接在 MySQL 里执行,建一个能支撑基本业务的库。字符集用utf8mb4,否则宠物昵称里的特殊符号会存成问号。

CREATE DATABASE pet_manage DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE pet_manage; CREATE TABLE owner ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL COMMENT '主人姓名', phone VARCHAR(20) NOT NULL COMMENT '联系电话', address VARCHAR(200) COMMENT '地址', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT '宠物主人表'; CREATE TABLE pet ( id BIGINT PRIMARY KEY AUTO_INCREMENT, owner_id BIGINT NOT NULL COMMENT '关联主人', pet_name VARCHAR(50) NOT NULL COMMENT '宠物名', species VARCHAR(20) COMMENT '种类,猫/狗/其他', breed VARCHAR(50) COMMENT '品种', birth_date DATE COMMENT '出生日期', weight DECIMAL(5,2) COMMENT '体重kg', INDEX idx_owner (owner_id) ) COMMENT '宠物表'; CREATE TABLE boarding ( id BIGINT PRIMARY KEY AUTO_INCREMENT, pet_id BIGINT NOT NULL, check_in DATE NOT NULL COMMENT '入住日期', check_out DATE COMMENT '离店日期', daily_price DECIMAL(8,2) NOT NULL COMMENT '每日单价', status TINYINT DEFAULT 1 COMMENT '1在住 2已离店', INDEX idx_pet (pet_id) ) COMMENT '寄养记录表';

字段说明:owner_id和pet_id用 BIGINT 是为了避免后期数据量大时改类型;daily_price存在寄养记录里而不是宠物表里,因为不同时期价格可能调整,历史账单不能被新价格污染;status用数字而不是字符串,查询和索引效率更高。建完表先手动插两条测试数据,确认外键逻辑没问题再写代码。

2.3 用 MyBatis 写第一个可运行的查询接口

Spring Boot 项目里,application.yml配好数据库连接,然后写 Mapper 接口和 XML。下面是一个按主人手机号查其名下所有宠物的例子。

// PetMapper.java @Mapper public interface PetMapper { // 根据主人手机号查询宠物列表 List<Pet> selectByOwnerPhone(@Param("phone") String phone); }
<!-- PetMapper.xml --> <select id="selectByOwnerPhone" resultType="com.example.pet.entity.Pet"> SELECT p.* FROM pet p LEFT JOIN owner o ON p.owner_id = o.id WHERE o.phone = #{phone} </select>

逻辑说明:用 LEFT JOIN 而不是 INNER JOIN,是为了防止主人信息缺失时宠物直接查不出来,方便排查脏数据。#{phone}是预编译占位符,能防 SQL 注入,不要写成${phone}。参数说明:@Param("phone")里的名字要和 XML 里#{}保持一致,否则启动就报绑定异常。写完先写一个 JUnit 测试或直接用 Postman 调 Controller,确认返回 JSON 里宠物列表不为空,再继续做新增和修改。

3. 核心功能落地:寄养计费、疫苗提醒与增删改查

3.1 寄养费用计算:别把日期差算成天数差

寄养费用最常见的错误是用check_out - check_in得到毫秒数再除以 86400000,结果住 3 天算成 2 天。正确做法是按自然日计算,入住当天算一天,离店当天不算。下面是一个 Service 层的方法。

public BigDecimal calcBoardingFee(LocalDate checkIn, LocalDate checkOut, BigDecimal dailyPrice) { if (checkOut == null) { checkOut = LocalDate.now(); // 未离店按当前日期试算 } long days = ChronoUnit.DAYS.between(checkIn, checkOut); if (days <= 0) { days = 1; // 当天入住当天走,至少收一天 } return dailyPrice.multiply(BigDecimal.valueOf(days)); }

逻辑说明:用ChronoUnit.DAYS直接算日期差,避免时区和毫秒误差。参数说明:dailyPrice用 BigDecimal,不要用 double,否则 0.1+0.2 这类精度问题会让账单出现 0.30000000000000004。如果业务规定「住满 24 小时才算一天」,那就要用 LocalDateTime 并额外判断小时数,但大多数宠物店按自然日结算,上面这个版本够用。

3.2 疫苗到期提醒:用 SQL 筛比在 Java 里循环靠谱

疫苗提醒的逻辑是:查出所有next_date在当前日期之后 7 天内的记录。不要在 Java 里把所有疫苗记录查出来再循环判断,数据量一大就慢。直接在 Mapper 里写条件查询。

<select id="selectExpiringVaccines" resultType="com.example.pet.entity.Vaccine"> SELECT v.*, p.pet_name, o.phone FROM vaccine v JOIN pet p ON v.pet_id = p.id JOIN owner o ON p.owner_id = o.id WHERE v.next_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY) ORDER BY v.next_date ASC </select>

逻辑说明:BETWEEN包含边界,CURDATE()只取日期部分,避免时间戳干扰。参数说明:INTERVAL 7 DAY里的 7 可以改成配置项,比如从application.yml读pet.vaccine.remind-days,方便不同门店调整。查出来的结果可以直接推给前端做提醒列表,也可以接短信或邮件,但短信接口涉及第三方费用,课程设计阶段用页面提醒就够了。

3.3 增删改查的四个接口与参数校验

宠物管理系统的增删改查不是简单调 Mapper,每个操作都要加校验。新增宠物时,owner_id必须存在,pet_name不能为空,birth_date不能晚于今天。修改时,如果宠物已经有关联的寄养记录,不允许直接删除,只能标记为「已归档」。下面是一个 Controller 层的片段。

@PostMapping("/pet/add") public Result addPet(@RequestBody @Valid Pet pet) { // 校验主人是否存在 Owner owner = ownerMapper.selectById(pet.getOwnerId()); if (owner == null) { return Result.fail("主人不存在"); } petMapper.insert(pet); return Result.success("添加成功"); }

逻辑说明:@Valid配合实体类上的@NotBlank、@Past等注解做基础校验,业务校验放在 Service 或 Controller 里。参数说明:Result是统一返回包装类,包含code、msg、data三个字段,前端好处理。删除接口建议做成逻辑删除,在表里加is_deleted字段,查询时默认过滤,这样误删了还有后悔药。

4. 避坑与排查:从启动报错到数据对不上

4.1 启动报Invalid bound statement (not found)

现象:Spring Boot 启动正常,一调 Mapper 方法就报这个错。原因通常是 XML 文件没被扫描到,或者namespace写错。解决:检查application.yml里mybatis.mapper-locations是否指向classpath:mapper/*.xml,检查 XML 的namespace是否和 Mapper 接口全限定名完全一致,包括大小写。如果用的是 Maven,确认src/main/resources下的 XML 被正确打包。

4.2 中文乱码:数据库、连接、页面三处都要查

现象:宠物名存进去变成???。原因可能是数据库字符集不是utf8mb4,或者 JDBC URL 没加characterEncoding=utf8。解决:建库时指定utf8mb4,连接串写成jdbc:mysql://localhost:3306/pet_manage?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai。如果页面还乱码,检查返回头的Content-Type是否带charset=UTF-8。

4.3 日期字段差一天:时区在捣鬼

现象:前端传2024-05-01,数据库存成2024-04-30。原因通常是 JDBC 连接没指定时区,或者实体类用了java.util.Date而数据库是DATE。解决:连接串加serverTimezone=Asia/Shanghai,实体类日期字段优先用LocalDate和LocalDateTime,MyBatis 从 3.4.5 起已原生支持。

4.4 外键约束导致删除失败

现象:删除主人时报Cannot delete or update a parent row。原因是有宠物还关联着这个主人。解决:要么先删宠物再删主人,要么在数据库层面设置ON DELETE CASCADE,要么在业务层做逻辑删除。课程设计里建议用逻辑删除,避免级联删除把诊疗记录也清掉。

4.5 分页查询总数不对

现象:列表只显示 10 条,但总数显示 100 条。原因通常是分页插件只对查询语句加了LIMIT,没执行 count 查询,或者 count 查询里带了ORDER BY导致效率低。解决:用 PageHelper 时,PageHelper.startPage(pageNum, pageSize)后面紧跟的查询才会被分页,count 由插件自动生成。如果手写分页,count 语句要去掉ORDER BY。

5. 论文与源码怎么讲清楚:从 ER 图到测试用例的落地技巧

5.1 论文框架别从「绪论」硬憋,先画三张图

写论文最卡的是第一章。我的习惯是先画 ER 图、系统架构图、核心业务流程图,这三张图一出来,需求分析和数据库设计两章就有了骨架。ER 图里把owner、pet、boarding、vaccine四个实体的属性和关系标清楚,一对多关系用 1:N 标注。架构图就画 Controller、Service、Mapper、MySQL 四层,旁边标注每层职责。流程图重点画寄养从入住到结算的完整路径,包括异常分支比如「提前离店」。图不要用花哨工具,draw.io 或 ProcessOn 导出 PNG 插入 Word 就行,关键是字段名和代码里一致。

5.2 测试用例表比截图更有说服力

论文里的「系统测试」章节,不要只贴几张页面截图。做一个测试用例表,包含用例编号、测试功能、输入数据、预期结果、实际结果、是否通过。比如「寄养费用计算」这条:输入入住 2024-05-01、离店 2024-05-04、单价 50,预期 150 元,实际 150 元,通过。再补一条边界用例:当天入住当天离店,预期 50 元。这样导师一看就知道你真的跑过,不是纯写文档。

用例编号测试功能输入数据预期结果实际结果
TC-01新增宠物主人ID=1,宠物名=豆豆添加成功添加成功
TC-02寄养计费5月1日入住,5月4日离店,单价50150元150元
TC-03疫苗提醒疫苗到期日=今天+3天出现在提醒列表出现在提醒列表
TC-04删除主人主人ID=1(有宠物关联)提示先处理宠物提示先处理宠物

5.3 源码整理:别把target和.idea一起打包

最后交付源码时,把target、.idea、*.iml、node_modules这些目录排除掉,只留src、pom.xml、application.yml、sql脚本和README.md。README 里写清楚:JDK 版本、MySQL 版本、导入 SQL 的顺序、启动命令、默认端口。如果附带视频,视频里重点演示「从空库到跑通第一个查询」的过程,不要从头到尾念代码。论文和源码的对应关系在 README 里列一个表:论文第几章对应哪个包或哪个类,导师查重和答辩时都能快速定位。

我自己的习惯是,每次改完代码先跑一遍 TC-01 到 TC-04 这四条用例,确认核心链路没断,再动其他功能。这套东西不难,难的是字段命名统一、日期处理不拍脑袋、删除之前想清楚关联。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 5:39:19

北京靠谱的星链AI应用服务商推荐:聚焦智能筛选与精准匹配场景

天津星链魔方企业管理有限公司是一家专注GEO品牌营销、AI全域营销、企业获客、新媒体营销、企业管理咨询的综合服务企业&#xff0c;核心业务围绕AI营销获客体系搭建、企业数字化落地展开&#xff0c;为不同发展阶段的企业提供从诊断到落地的全链路营销解决方案。从企业营销痛点…

作者头像 李华
网站建设 2026/10/7 5:38:23

Python渗透测试脚本合集整理指南:环境隔离与脚本改造

简介&#xff1a;这是一份面向安全初学者与渗透测试从业者的Python实战脚本合集&#xff0c;围绕Python 3.9与Kali环境编写&#xff0c;强调用编程替代工具依赖&#xff0c;既可用于实战演练&#xff0c;也可作为Python安全编程的学习范例。资源共64个文件&#xff0c;以45个py…

作者头像 李华
网站建设 2026/10/7 5:37:27

WorkBuddy生产级实战:MCP协议陷阱与Skills链稳定性优化

1. 从“能用”到“敢交活”&#xff1a;WorkBuddy不是工具&#xff0c;是新同事三个月前&#xff0c;我把它当成一个高级版Copilot——写写周报、润润邮件、查查API文档。直到某天凌晨两点&#xff0c;客户临时要一份含5个数据维度、3种图表类型、带业务逻辑注释的销售复盘PPT&…

作者头像 李华
网站建设 2026/10/7 5:37:04

游戏引擎基础架构解析:主循环、分层设计与模块化实战

游戏引擎架构这个题目&#xff0c;我琢磨了很久才敢动手写。原因很简单&#xff1a;市面上讲引擎架构的书和文章并不少&#xff0c;但大部分要么停留在“引擎包含渲染、物理、音频等模块”这种概念罗列&#xff0c;要么一头扎进某个具体系统的源码细节里出不来。真正能把“引擎…

作者头像 李华
网站建设 2026/10/7 5:37:01

Sonnet 5.5偷跑背后:Claude Code配置、Token优化与Agent开发实战

1. 从"Sonnet 5.5偷跑"这个标题说起&#xff1a;大模型迭代节奏正在发生什么变化"偷跑"这个词在大模型圈子里已经不算新鲜了。所谓偷跑&#xff0c;通常指的是某个模型版本在官方正式发布之前&#xff0c;通过灰度接口、第三方平台、评测榜单或者开发者工具…

作者头像 李华
网站建设 2026/10/7 5:34:59

PandarView点云可视化实战:从安装到实时数据采集的完整指南

PandarView点云可视化是我这些年折腾激光雷达数据时用得最顺手的一个工具&#xff0c;没有之一。做LiDAR相关工作的人应该都有体会&#xff1a;点云数据拿到了&#xff0c;但想快速看一眼这帧数据长得像什么、遮挡关系如何、远处噪点多不多&#xff0c;如果手里没有一套趁手的可…

作者头像 李华