SpringBoot药店管理系统课设毕设:库存扣减与处方药校验实战

发布时间:2026/9/30 10:37:15

SpringBoot药店管理系统课设毕设:库存扣减与处方药校验实战 简介这份资源是面向高校计算机相关专业学生与Java Web初学者的一套药店管理系统课程设计/毕业设计完整方案基于SpringBoot框架实现适合需要完成课设毕设或想通过真实项目入门SpringBoot开发的人群。压缩包约15.96MB内含论文、开题报告、数据库脚本、说明文档及可运行源码覆盖用户管理、药品管理、订单管理、库存管理等核心模块并涉及Spring Security或JWT鉴权、Spring Data JPA或MyBatis持久化、事务管理等技术要点。说明文档与项目说明书可帮助读者快速配置环境、理解系统架构与接口设计源码则便于对照学习控制器、服务、模型、视图各层的组织方式。目前已有68人学习下载适合希望系统掌握SpringBoot实践应用、了解药店业务流程与软件开发全流程的读者参考。1. 药店管理系统课设毕设从一份可运行源码里能学到什么很多同学拿到「课设毕设springboot基于Java web的药店管理系统」这类题目时第一反应是去搜一份能跑的源码改改包名、换个数据库密码能启动、能截图、能写进论文就算交差。但真正答辩被追问「库存扣减怎么保证不超卖」「处方药和OTC药品的销售逻辑有什么区别」「为什么用SpringBoot而不是Servlet」时往往答不上来。这篇笔记不打算复述某份源码的目录结构而是顺着这个标题把一套药店管理系统从技术选型、数据库设计、核心业务实现到部署排错完整拆一遍让你既能照着搭出一个能跑的系统也能在答辩和后续面试里讲清楚每个决策背后的理由。药店管理系统本质上是一个带库存约束的进销存系统比普通CRUD的图书管理、学生管理要复杂一档药品有批号、有效期、处方药/非处方药分类销售时要校验库存和处方采购入库要更新批次过期药品要能预警。这些才是这个题目真正值得做的地方也是面试官和答辩老师会盯的点。适合正在做Java web方向课设毕设的本科生也适合想用一个完整项目复习SpringBoot MyBatis MySQL这套组合的初级开发者。下面按「先立住技术选型 → 再动手建库建表 → 实现核心业务 → 排坑 → 进阶」的顺序推进每一步都给到能直接抄的命令和代码。2. 技术选型与工程骨架为什么是SpringBoot而不是纯Servlet2.1 药店管理系统的分层与依赖取舍一套能写进毕设、也能经得起追问的药店管理系统常见做法是经典三层Controller 接请求、Service 写业务、Mapper 落库。SpringBoot 在这里的价值不是「新」而是把 Tomcat 内嵌、依赖注入、事务管理、JSON 序列化这些重复劳动一次性配好让你把精力放在药品库存这种真正的业务逻辑上。如果坚持用纯 Servlet JSP光是配置 web.xml、手动管理连接池、手写 JSON 转换就能吃掉大半时间而且事务边界很难控制——药品销售时「扣库存 写销售单 写流水」必须在一个事务里Servlet 里手写connection.setAutoCommit(false)很容易漏。选型上我一般会这样定SpringBoot 2.7.x3.x 要求 JDK17很多学校机房还是 JDK8别踩这个坑、MyBatis 或 MyBatis-Plus 做持久层、MySQL 5.7/8.0、前端用 Thymeleaf 或直接前后端分离走 Vue。热词里提到的「springboot vue前后端分离」是现在毕设的主流形态但如果时间紧Thymeleaf 服务端渲染能省掉跨域、Token 传递一堆事先把业务跑通更重要。依赖清单pom.xml 关键部分parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version /parent dependencies !-- Web 层内嵌 Tomcat -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 持久层MyBatis 官方 starter -- dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version /dependency !-- MySQL 驱动8.0 用 com.mysql.cj.jdbc.Driver -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- 参数校验药品表单必填项靠它 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency /dependencies这段配置的逻辑是spring-boot-starter-web负责把 DispatcherServlet、Jackson、内嵌容器都拉进来mybatis-spring-boot-starter让 Mapper 接口能被自动扫描注册省掉SqlSessionFactory的手工配置validation 用来在 Controller 层拦截药品名称、价格、库存这些字段的非法输入。参数上唯一要注意的是版本对齐——SpringBoot 2.7.x 配 MyBatis starter 2.3.x 是稳的别混用 3.x 的 starter会出现NoSuchMethodError。2.2 用 IDEA 或命令行把骨架跑起来如果你用 IDEA直接 Spring Initializr 勾选 Spring Web、MyBatis Framework、MySQL Driver 即可。命令行党可以用 curl 拉骨架或者干脆手写。启动类长这样SpringBootApplication MapperScan(com.example.pharmacy.mapper) // 扫描 Mapper 接口漏了会报找不到 Bean public class PharmacyApplication { public static void main(String[] args) { SpringApplication.run(PharmacyApplication.class, args); } }MapperScan是最容易漏的一行漏了之后启动不报错但一调用就抛Field xxxMapper required a bean新手经常在这里卡半天。配置文件application.ymlserver: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/pharmacy?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml # XML 映射文件位置 configuration: map-underscore-to-camel-case: true # 下划线转驼峰drug_name - drugNameserverTimezone不写会报时区错误map-underscore-to-camel-case不写会导致数据库drug_name映射不到实体drugName查出来全是 null。这两个是血泪经验级别的必配项。跑通的标准是访问http://localhost:8080不报 404、控制台没有数据源异常此时骨架就算立住了。3. 数据库设计药品、批次、库存三张表怎么拆3.1 从业务反推表结构药店管理最容易设计错的地方是把「药品」和「库存」混成一张表。正确的拆法是药品表存药品的静态属性名称、规格、厂家、是否处方药批次表存每一批进货的批号、生产日期、有效期、进价库存表或直接在批次表上用数量字段表示当前剩余。销售时按批次先进先出FIFO扣减这样才能支持有效期预警和批次追溯。核心表结构表名关键字段说明drugid, drug_name, spec, manufacturer, is_rx, price药品基础信息is_rx 标记处方药drug_batchid, drug_id, batch_no, produce_date, expire_date, cost_price, quantity批次与库存quantity 为剩余量sale_orderid, order_no, total_amount, create_time, operator销售主单sale_itemid, order_id, batch_id, quantity, unit_price销售明细关联具体批次purchase_orderid, supplier, total_amount, status采购单status 控制入库流程这样拆的好处是库存扣减落在drug_batch.quantity上天然支持多批次有效期预警只需SELECT * FROM drug_batch WHERE expire_date DATE_ADD(NOW(), INTERVAL 30 DAY)批次追溯通过 sale_item 反查 batch_no 即可。3.2 建表 SQL 与索引CREATE TABLE drug ( id BIGINT PRIMARY KEY AUTO_INCREMENT, drug_name VARCHAR(100) NOT NULL, spec VARCHAR(50), manufacturer VARCHAR(100), is_rx TINYINT DEFAULT 0 COMMENT 0非处方 1处方, price DECIMAL(10,2) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE drug_batch ( id BIGINT PRIMARY KEY AUTO_INCREMENT, drug_id BIGINT NOT NULL, batch_no VARCHAR(50) NOT NULL, produce_date DATE, expire_date DATE NOT NULL, cost_price DECIMAL(10,2), quantity INT NOT NULL DEFAULT 0, INDEX idx_drug_id (drug_id), INDEX idx_expire (expire_date) -- 有效期预警走这个索引 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;idx_expire这个索引是给预警查询用的不加的话数据量一上来全表扫描会明显变慢。quantity用 INT 而不是无符号是因为扣减时如果逻辑写错出现负数无符号会直接报错中断事务而有符号能让你在日志里看到 -1 这种异常值方便定位问题——这是排查思路上的取舍不是设计缺陷。提示字符集统一用 utf8mb4药品名里出现生僻字或特殊符号时 utf8 会插入失败。4. 核心业务实现库存扣减与处方药校验4.1 销售下单的事务与防超卖销售是这套系统的心脏。一次销售要完成校验处方药是否有处方、按 FIFO 选批次、扣减库存、写销售单和明细。整个过程必须在一个事务里且扣库存要用带条件的 UPDATE 防止并发超卖。Service public class SaleService { Autowired private DrugBatchMapper batchMapper; Autowired private SaleOrderMapper orderMapper; Transactional(rollbackFor Exception.class) // 任何异常都回滚 public void sell(Long drugId, int num, boolean hasPrescription) { // 1. 处方药校验非处方药直接放行 Drug drug batchMapper.selectDrugById(drugId); if (drug.getIsRx() 1 !hasPrescription) { throw new BizException(处方药必须凭处方销售); } // 2. 按有效期升序取批次先进先出 ListDrugBatch batches batchMapper.selectAvailableBatches(drugId); int remain num; for (DrugBatch b : batches) { if (remain 0) break; int deduct Math.min(remain, b.getQuantity()); // 3. 带条件的更新quantity deduct 才扣防止并发扣成负数 int rows batchMapper.deductStock(b.getId(), deduct); if (rows 0) { throw new BizException(库存不足批次 b.getBatchNo()); } remain - deduct; } if (remain 0) { throw new BizException(总库存不足); } // 4. 写销售单 orderMapper.insertOrder(drugId, num); } }对应的 Mapper SQLupdate iddeductStock UPDATE drug_batch SET quantity quantity - #{deduct} WHERE id #{batchId} AND quantity #{deduct} /update关键在AND quantity #{deduct}这个条件。它把「判断库存够不够」和「扣减」合并成一条原子 SQL靠数据库行锁保证并发安全。如果先 SELECT 查库存再 UPDATE两个请求同时查到库存 1就会都扣成功变成 -1这就是超卖。Transactional的rollbackFor Exception.class也不能省默认只回滚 RuntimeException自定义的受检异常不回滚会留下脏数据。4.2 有效期预警与采购入库有效期预警是个定时任务或手动触发的查询逻辑简单但很能体现业务理解Select(SELECT b.*, d.drug_name FROM drug_batch b JOIN drug d ON b.drug_id d.id WHERE b.expire_date DATE_ADD(CURDATE(), INTERVAL #{days} DAY) AND b.quantity 0 ORDER BY b.expire_date) ListBatchVO selectExpiringBatches(Param(days) int days);days参数一般设 30 或 90代表提前多少天预警。quantity 0是为了过滤掉已经卖完的批次否则预警列表里全是历史空批次没有意义。采购入库则是反向操作新增批次记录或对已有批次加数量同时写采购单。入库时要注意批号唯一性——同一药品同一批号重复入库应该合并数量而不是插两条否则 FIFO 逻辑会乱。5. 避坑与排查那些让系统跑不起来的细节5.1 启动就报数据源或 Mapper 找不到现象启动日志抛Failed to configure a DataSource或调用接口时Invalid bound statement (not found)。原因通常是application.yml里数据源配置的缩进错了YAML 对缩进敏感或者mapper-locations路径和实际 XML 位置对不上。解决先确认spring.datasource下的 url/username/password 是同级缩进再确认 XML 放在src/main/resources/mapper/下且mapper-locations写的是classpath:mapper/*.xml。Invalid bound statement还有可能是 Mapper 接口方法名和 XML 里的 id 不一致逐字对一遍。5.2 中文乱码与时间差 8 小时现象药品名存进去变成问号或者创建时间比实际早/晚 8 小时。原因是数据库连接没指定字符集和时区。解决JDBC url 里加useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai同时确认建表用的是 utf8mb4。时区问题如果只加serverTimezoneUTC会差 8 小时必须写Asia/Shanghai。5.3 事务不回滚导致库存扣了单没生成现象库存扣减成功但销售单没写进去数据不一致。原因是Transactional加在了 private 方法上或者同类内部方法直接调用this.xxx()绕过了代理。解决事务方法必须是 public且通过 Spring 注入的 Bean 调用不能在同一个类里自调用。另外确认异常类型在rollbackFor范围内。5.4 前端传参后端收不到现象POST 提交药品表单后端RequestBody收到的字段全是 null。原因是前端发的是application/x-www-form-urlencoded而后端按 JSON 解析。解决要么前端改成JSON.stringify并设Content-Type: application/json要么后端改用ModelAttribute接收表单。前后端分离项目里这个错最常见抓包看 Content-Type 一眼就能定位。5.5 打包成 jar 后访问 404现象IDEA 里跑得好好的mvn package后java -jar启动接口全 404。原因是静态资源或模板没被打进 jar或者 Controller 扫描路径不对。解决确认SpringBootApplication所在包是所有 Controller 的父包静态资源放src/main/resources/staticThymeleaf 模板放templates。打包后可以用jar tf target/xxx.jar | grep templates确认文件在不在里面。6. 从能跑到能讲把项目变成答辩和面试的加分项系统跑通只是及格线真正拉开差距的是你能不能讲清楚设计取舍。我一般会建议在基础功能之上加两个能体现思考的点。第一个是库存扣减的并发验证写一个简单的压测脚本用 JMeter 或干脆用 Java 起 50 个线程同时下单同一批次观察最终库存是否等于初始值减去成功订单数。如果出现负数或对不上说明你的条件 UPDATE 或事务边界有问题。这个实验做一遍答辩时讲「我用带条件的原子更新防止超卖」就非常有底气。// 并发验证片段50 个线程抢 10 件库存 ExecutorService pool Executors.newFixedThreadPool(50); CountDownLatch latch new CountDownLatch(1); AtomicInteger success new AtomicInteger(); for (int i 0; i 50; i) { pool.submit(() - { try { latch.await(); // 等发令枪保证同时开抢 saleService.sell(1L, 1, true); success.incrementAndGet(); } catch (Exception e) { // 库存不足的异常正常 } }); } latch.countDown(); pool.shutdown(); pool.awaitTermination(10, TimeUnit.SECONDS); System.out.println(成功下单数 success.get()); // 期望等于 10第二个是有效期预警的可视化把 30 天内到期的批次做成首页红黄灯列表答辩演示时非常直观。进阶方向还可以接 MinIO 存药品图片、用全局过滤器处理上传文件的 XSS 风险这些热词里提到的点都能作为扩展写进论文的「系统优化」章节但前提是核心业务先扎实。最后说个我自己的习惯每写完一个 Service 方法我都会问自己一句「如果这个方法被同时调用 100 次数据会不会乱」。药店管理系统的价值不在页面多漂亮而在库存和金额这些数字永远对得上。把这句话刻在脑子里你的课设就不只是能跑而是能讲、能扛追问。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/9/30 10:32:13

真正的AI能力,从来不是始于完美指令

在AI普及的当下,“指令越精准,结果越优质”几乎成为公认的使用准则。无数教程、经验帖都在强调精准提示词的重要性,告诉我们只有给出清晰、具体、完备的指令,才能让AI精准落地需求。但回归真实的工作与生活,我们会发现…

2026/9/30 10:32:13

CentOS虚拟机固定IP配置指南:从VMware网络模式到实操详解

1. 为什么要给CentOS虚拟机配置固定IP 1.1 动态IP带来的那些坑 先说个场景:你装了台CentOS虚拟机,平时用DHCP自动分配IP,一切正常。某天重启一下机器,SSH连不上了,一看IP地址变了。你之前部署的Nginx、MySQL、Redis&a…

2026/9/30 10:32:13

2021数学建模国赛复盘:三道题揭示建模三大范式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 11:32:55

校园二手交易App开发:Android原生毕设核心流程与工程实践

简介:一份基于Android Studio开发的校园二手交易系统完整App源码,面向毕业设计学生与Android初级开发者,可用于学习完整的移动端业务实现流程。项目以Java为主,辅以XML布局与Gradle构建脚本,zip压缩包共186个文件&…

2026/9/30 11:32:55

FoxyPreview:Windows轻量级文件预览工具深度指南

简介:FoxyPreview最新版是一款专为Visual FoxPro(VFP)开发者设计的报表预览与导出工具,面向使用VFP进行桌面应用开发的技术人员及维护工程师,解决传统VFP报表难以跨平台共享、二次处理与归档的痛点。资源包共245个文件…

2026/9/30 11:32:55

MCP传输层选型:SSE与Streamable HTTP原理、实操与避坑

第一次接触 MCP 的人,十有八九会在 streamable HTTP 和 SSE 这两个概念上卡住。我最初做 MCP Server 的时候也踩过不少坑,官方文档里一会儿提到 SSE,一会儿又推荐 streamable HTTP,再去看各种 SDK 的 transport 参数,整…

2026/9/30 11:32:55

电力远程运维系统四层架构实战:断网、多协议、等保2.0落地指南

简介:本资源是一套面向电力行业开发者的远程运维系统源码实现,聚焦配电房智能监控与设备维护管理场景,适用于具备Python和Web全栈基础的中级开发者学习IoT运维系统架构设计。压缩包共167个文件,含32个核心Python后端模块、29个HTM…

2026/9/30 11:32:55

打工人必看!5款AI一键生成PPT工具实测,第3个太逆天!

每次接到紧急汇报任务,看着空白的PPT页面发呆,是不是特别希望有个“外挂”能救场?尤其是年底总结、项目复盘、方案提案扎堆的时候,做PPT不仅耗时耗力,还经常因为排版不专业、配色辣眼睛被领导打回来重做。最近市面上涌…

2026/9/30 11:27:54

Meta Muse 长任务为什么越来越慢?原因、判断方法与提速指南

Meta Muse 执行几分钟以上的长任务时,有些用户会感觉它越跑越慢:前几步还能快速回复,后面开始长时间停留在“处理中”,生成文字的速度下降,网页操作也迟迟没有结果。 这类现象通常不能简单归结为“模型变笨了”。对于能…

2026/9/29 11:07:23

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/29 21:48:03

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 7:00:49

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/30 0:01:22

MATLAB+Yalmip+CPLEX实战:综合能源系统优化调度全流程解析

做综合能源系统优化调度这活儿,最痛苦的不是建模本身,而是模型写完之后不知道该怎么求解。看论文里轻飘飘一句“采用Yalmip调用CPLEX求解”,自己上手时却往往卡在环境配置、变量声明、约束写法和求解状态判读上,一耗就是两三天。这…

2026/9/30 0:01:22

I3C比I2C快10倍?RK3576实战:速率、DTS配置与混合总线避坑指南

I3C 比 I2C 快 10 倍?这句话在嵌入式群里传了很久,每次都能吵出一堆截图。前段时间我正好在 RK3576 上调板级 I3C 接口,从控制器寄存器一路摸到 Linux DTS 配置,踩了不少坑,也把这笔速度账彻底算明白了。本文就用 RK35…

2026/9/30 0:01:22

字符串转对象:JSON.parse、new Function与URLSearchParams

“字符串转对象”这几个字,我在技术群里见过的问法至少有十几种:有人拿着一串{a:1,b:2}说 JSON.parse 直接报错,有人要从 URL 里抠出参数,还有人只是想把abc变成能挂属性的东西。js 这门语言里,字符串和对象之间的转换…

2026/9/29 3:53:39

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/29 9:46:12

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/30 10:28:53

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑