资讯详情

基于若依的仓库管理系统:从脚手架到毕业设计实战攻略

📅 2026/10/9 4:26:09 | 华诺云谱 👁 阅读
基于若依的仓库管理系统:从脚手架到毕业设计实战攻略
简介基于若依框架的仓库管理系统源码与数据库适合用作Java毕业设计、课程设计或若依框架二次开发练习。项目源于医院口腔科精细化管理需求针对亚专科多、器械耗材种类繁杂、共用性差等难点实现了总库、二级库、三级库逐级申领与供给的仓库管理模式覆盖采购、出入库、核算等核心业务流程并可联动财会系统将成本分摊至医生个人形成监控与反馈闭环为同类场景提供了完整可落地的设计思路。压缩包共733个文件以Java源码、HTML页面、JS脚本、CSS样式、XML配置、VM模板、SQL脚本等为主体兼顾前端页面与后端逻辑另有较全的文档、启动脚本和数据库脚本包大小67.22MB目录层级分明便于按模块拆解和二次扩展。目前已有397人学习下载适合需要掌握若依框架、理解仓库管理业务流转并希望获得可运行示例项目作为设计参考的开发者。1. 基于若依的仓库管理系统这包东西要当成工程去学别当成作业去抄每年毕业季都会有一批人拿到一个名叫“基于若依的仓库管理系统源码数据库java毕业设计.zip”的压缩包解压之后看得到前端、后端和SQL脚本跑起来也能登录然后就以为毕业设计稳了。真正到答辩现场导师一句“入库单怎么让库存变少的”“菜单权限是若依给你做的还是你自己设计的”就能让很多人当场卡壳。这套方案本身没有问题以若依RuoYi-Vue为基座用 Spring Boot MyBatis/MyBatis-Plus Vue 这套主流 Java 技术栈做一套包含物料、供应商、出入库单据、库存台账和基础报表的仓库管理系统。问题是大部分人只把若依当成了一个“后台模板”而没有把它当成一个可以讲清楚原理的工程去拆解。这篇文章就沿着“它是什么、怎么落地、坑在哪、怎么验收”往下讲适合正在做 Java 毕设、或者想用若依快速搭后台管理系统的人。2. 为什么拿若依做仓库系统脚手架在替你扛哪些事2.1 若依真正在帮你解决的不是 CRUD而是权限与流程控制仓库管理系统从功能上看无非是物料档案的增删改查、出入库单的数据录入、库存的加减和报表的展示。如果只凭 Spring Boot 自己写最先要解决的反而不是业务而是“谁能登录、谁能点这个按钮、谁能看这组数据”这一套后台权限问题。而这套东西恰好是若依这类后台脚手架最大的价值。若依在仓库系统里替你垫好的地基至少有五块。第一是用户、角色、菜单三层权限模型sys_user、sys_role、sys_menu 三张表把“谁是什么角色角色能看哪些菜单菜单里的按钮是否可见”全部串起来第二是登录认证和会话管理RuoYi-Vue 的登录令牌和验证码都依赖 Redis 存储第三是代码生成器它能把一张数据库表直接生成 Controller、Service、Mapper、Vue 页面和一串菜单 SQL第四是字典管理仓库里的计量单位、单据状态、是否删除这类固定枚举值可以交给数据字典维护第五是操作日志与定时任务仓库的出入库记录可以自动留痕批次盘点之类的任务也能挂到定时任务里。权限这一层需要真正理解而不是只会点鼠标。比如你给“入库单管理”写一个新增按钮的接口Controller 方法上一般会加一个RequiresPermissions(wms:inbound:add)注解前端的按钮上用v-hasPermi指令包一层这样权限标识对不上时按钮连渲染都不会渲染。仓库系统里最常见的账号分配方式就是管理员拥有全部菜单仓管员只能操作出入库单和库存查询访客只读报表。这三类角色在若依后台的“角色管理”里分配一次代码一行都不用改这就是脚手架的价值。2.2 仓库系统的业务边界先把“账”和“实”两套数据想清楚仓库管理系统和普通的信息管理系统最大的区别在于它存在“单据”和“库存”两条数据线。“单据”是账面上的业务凭证入库单记录了哪个供应商送了哪些货、数量多少、单价多少“库存”是实物账wms_stock 表里记录的是某个商品当前还剩多少。单据负责解释库存为什么变动库存则决定当前还能不能发货。这个关系如果没搞明白系统做出来就是一个“带壳子的增删改查”。模块边界可以分为四块。基础资料包括物料档案、供应商档案、客户档案它们是单据的下拉选项来源单据管理包括采购入库单、销售出库单、退货单每张单都有主表和明细表主表保存单号和状态明细表保存货品和数量库存管理包括库存台账、库存流水、安全库存预警统计分析包括入库汇总、出库汇总、当前库存列表。毕设做到这个范围已经非常完整了。注意不要往制造执行系统MES那个方向扯MES 里还有工单、工艺路线、排产、设备数据采集那已经是另一套系统不是这个标题能覆盖的。我一般会跟人强调图纸画得越细后面写代码越轻松。仓库系统核心的一张图就是“入库过账和出库过账如何影响库存”入库单审核后在同一个事务里把明细数量累加到 wms_stock出库单审核后在同一事务里做扣减。这里必须用Transactional保证要么都成功、要么都失败否则会出现“单据审核通过了库存没动”这种账实不符的严重问题。2.3 RuoYi-Vue、RuoYi-Plus 与若依微服务毕设到底选哪条线拿到源码包后第一件事是确认项目属于若依哪个分支。常见的是 RuoYi-Vue即前后端分离的单体应用后端一个 Spring Boot 工程前端是 Vue2 Element UI另一个是 RuoYi-Plus它在若依-Vue 的基础上做了很多现代化重构前端升级到 Vue3 Element Plus TypeScript后端引入了 MyBatis-Plus认证方式也换了更轻量的实现。还有一套若依微服务 Plus把系统拆成多个服务配合网关和注册中心使用部署复杂度明显更高。从毕业设计的角度我的建议非常明确只要源码包是 RuoYi-Vue就老老实实在这条线上做如果手头是 RuoYi-Plus也不要去换成微服务。单体应用部署简单、代码点少、答辩时容易讲清楚一个 RuoYiApplication 启动类就是后端的入口前端一个npm run dev就能起来这比微服务里“网关调用用户服务再调用业务服务”的解释成本低太多。打开 pom.xml 看一眼 spring-boot-starter-parent 的版本和依赖列表就能确认是哪一代的若依。选型的核心逻辑是毕业答辩看的是你对自己系统的理解深度不是技术栈够不够新。3. 仓库管理系统的表设计与若依对接四张核心业务表和菜单权限挂接3.1 先分清若依自带表和业务表sys_ 开头的表别乱动初始化若依项目时数据库脚本会创建一大批以 sys_ 开头的系统表。sys_user 是用户表sys_role 是角色表sys_menu 是菜单表sys_user_role 和 sys_role_menu 是关联表。admin 初始账号就存在 sys_user 里。你在做仓库系统时凡是跟用户、角色、菜单、字典、参数、日志相关的表全部属于若依的领地不要去改它们的表结构更不要在业务代码里去 join 它们。仓库业务表则建议单独建在同一个库里统一用 wms_ 前缀这样一眼就能区分哪些是脚手架的表、哪些是你自己设计的表。业务表命名通常遵循两个约定主表不带 _item 后缀如图 wms_inbound明细表带 _item 后缀如 wms_inbound_item。所有业务表都建议带上 create_by、create_time、update_by、update_time、remark 这五个若依约定字段这样代码生成器生成的实体类和页面会自动把创建人、创建时间识别出来。3.2 仓库系统核心 DDL我个人习惯直接手写建表语句虽然可以用若依的代码生成器反向生成表但仓库系统的表之间有主外键语义和库存计算逻辑我建议先手写 DDL再由表去生成代码。下面是四张核心表的建表语句可以直接在若依的数据库里执行。-- 物料档案表 CREATE TABLE wms_product ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键, product_code VARCHAR(64) NOT NULL COMMENT 物料编码, product_name VARCHAR(128) NOT NULL COMMENT 物料名称, spec VARCHAR(128) DEFAULT NULL COMMENT 规格型号, unit VARCHAR(16) DEFAULT NULL COMMENT 计量单位, category VARCHAR(64) DEFAULT NULL COMMENT 物料分类, warning_stock INT DEFAULT 0 COMMENT 安全库存, create_by VARCHAR(64) DEFAULT COMMENT 创建者, create_time DATETIME DEFAULT NULL COMMENT 创建时间, update_by VARCHAR(64) DEFAULT COMMENT 更新者, update_time DATETIME DEFAULT NULL COMMENT 更新时间, remark VARCHAR(500) DEFAULT NULL COMMENT 备注, del_flag CHAR(1) DEFAULT 0 COMMENT 删除标志, PRIMARY KEY (id), UNIQUE KEY uk_product_code (product_code) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 物料档案表; -- 库存台账表 CREATE TABLE wms_stock ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键, product_id BIGINT NOT NULL COMMENT 物料ID, quantity INT DEFAULT 0 COMMENT 当前库存数, locked_quantity INT DEFAULT 0 COMMENT 锁定库存数, create_time DATETIME DEFAULT NULL COMMENT 创建时间, update_time DATETIME DEFAULT NULL COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_product_id (product_id) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 库存台账表; -- 入库单主表 CREATE TABLE wms_inbound ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键, inbound_no VARCHAR(32) NOT NULL COMMENT 入库单号, supplier_id BIGINT DEFAULT NULL COMMENT 供应商ID, status CHAR(1) DEFAULT 0 COMMENT 单据状态0草稿1已过账, inbound_date DATETIME DEFAULT NULL COMMENT 入库日期, create_by VARCHAR(64) DEFAULT COMMENT 创建者, create_time DATETIME DEFAULT NULL COMMENT 创建时间, update_by VARCHAR(64) DEFAULT COMMENT 更新者, update_time DATETIME DEFAULT NULL COMMENT 更新时间, remark VARCHAR(500) DEFAULT NULL COMMENT 备注, del_flag CHAR(1) DEFAULT 0 COMMENT 删除标志, PRIMARY KEY (id), UNIQUE KEY uk_inbound_no (inbound_no) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 入库单主表; -- 入库单明细表 CREATE TABLE wms_inbound_item ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键, inbound_id BIGINT NOT NULL COMMENT 入库单主表ID, product_id BIGINT NOT NULL COMMENT 物料ID, quantity INT NOT NULL DEFAULT 0 COMMENT 入库数量, price DECIMAL(10, 2) DEFAULT 0 COMMENT 单价, amount DECIMAL(12, 2) DEFAULT 0 COMMENT 金额, PRIMARY KEY (id), KEY idx_inbound_id (inbound_id) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 入库单明细表;出库单 wms_outbound 和 wms_outbound_item 的结构与入库表基本一致把 supplier_id 换成 customer_id 即可。这套设计有四个关键点主表和明细表拆分是因为一张入库单可以包含多个物料明细表通过 inbound_id 关联主表库存单独建表而不是直接在产品表里加数量字段是为了避免每次查库存都把产品主数据一起锁住也方便以后扩展库位和批次明细表里的 price 和 amount 是业务快照物料价格会变但单据上的历史价格必须保持不变del_flag 字段配合 MyBatis-Plus 的TableLogic注解可以实现逻辑删除数据库里不会真删数据所有历史单据都能追溯。关于 MyBatis-Plus 根据实体类生成建表 SQL 的做法如果你拿到的是 RuoYi-Plus 版本也可以先写实体类再用工具输出 CREATE TABLE 语句。但仓库系统这种表关系我建议“先建表再生成代码”因为表格关系在 SQL 里看得更直观生成器也更容易正确处理主表与明细表的关系。3.3 用若依代码生成器落地面向表的增删改查表建好以后在若依后台“系统工具 - 代码生成”里导入这四张表就可以生成整套 CRUD 代码。生成前有几个配置必须调整生成信息里的“生成包路径”填com.ruoyi.wms“生成模块名”填wms“上级菜单”选一个自己创建的仓库管理目录字段信息里把 product_code、inbound_no 这类编号字段设为查询条件wms_stock 表的 quantity 字段建议设为不回显避免在物料编辑页面被直接改库存。生成器输出物包括 domain 实体类、mapper 接口和 XML、service 接口与实现类、controller 控制器、Vue 页面和三段菜单 SQL。其中菜单 SQL 通常包含一个目录菜单和两个页面菜单直接执行就能把功能挂进左侧菜单。代码生成器的边界要清楚它生成的是标准的数据库增删改查仓库系统的过账逻辑、库存校验、事务控制必须自己写不能指望生成器帮你完成。3.4 菜单权限挂接不要在 parent_id 上翻车菜单挂接是把“页面存在”变成“用户可见”的最后一步。很多人在这一步把 parent_id 写错导致菜单树彻底乱掉。下面这段 SQL 是先创建一个顶级目录“仓库管理”再用LAST_INSERT_ID()拿到新菜单 ID 去挂子页面-- 创建顶级目录菜单parent_id 为 0 表示根节点 INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES (仓库管理, 0, 2, wms, NULL, 1, 0, M, 0, 0, NULL, example, admin, sysdate(), NULL); -- 创建子菜单parent_id 使用刚插入的菜单 ID INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES (入库管理, LAST_INSERT_ID(), 1, inbound, wms/inbound/index, 1, 0, C, 0, 0, wms:inbound:list, form, admin, sysdate(), NULL);这里最容易被忽略的是菜单插入 sys_menu 之后还要去“系统管理 - 角色管理”给对应角色重新分配菜单因为角色和菜单的关联存在 sys_role_menu 表里直接执行 SQL 不会自动补关联数据。菜单层级出现混乱时优先检查两个方向一个是子菜单的 parent_id 是否指向了正确的一级菜单 ID另一个是 sys_role_menu 里有没有记录。4. 把仓库系统在本地跑起来从建库到前后端打通的最小步骤4.1 建库导数据两条 SQL 脚本的执行顺序不能反拿到的 Zip 里通常会有两个 SQL 文件一个是若依的基础库脚本包含 sys_ 开头的系统表和 admin 初始数据另一个是仓库业务表和菜单数据的脚本。执行顺序必须先把若依基础库导入再导入仓库业务脚本。如果反过来业务菜单里关联的 parent_id 在 sys_menu 里还找不到对应记录菜单就挂不上去。# 创建数据库指定 utf8mb4 字符集 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS ruoyi_wms DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 先导入若依基础库脚本 mysql -uroot -p ruoyi_wms ruoyi_base.sql # 再导入仓库业务表和菜单数据脚本 mysql -uroot -p ruoyi_wms wms_business.sqlutf8mb4 必须指定因为若依的菜单图标、备注里可能包含特殊字符业务数据里也可能有中文与表情符号用默认的 utf8 会在导入时偶发字符集报错。导入时如果提示表已存在先执行DROP TABLE IF EXISTS或者在库上重建一个干净数据库不要直接在旧库上反复追加。4.2 改后端配置数据源、Redis、日志路径三处最常出问题后端工程里要修改的核心配置文件是application-druid.yml和application.yml。数据源改成你自己的 MySQL 账号Redis 地址改成 127.0.0.1。网上很多若依配置教程会让你只改数据源但若依的登录验证码和用户 token 都存在 Redis 里Redis 连不上时页面会一直报“验证码获取失败”或登录请求超时。spring: datasource: druid: master: url: jdbc:mysql://localhost:3306/ruoyi_wms?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8 username: root password: 你的数据库密码 redis: host: 127.0.0.1 port: 6379 password: database: 0url 里的serverTimezoneGMT%2B8是时区参数不写的话 MySQL 8.0 以上版本会在启动时报时区错误zeroDateTimeBehaviorconvertToNull是兼容零日期值的若依的基础数据里有不少空时间这个参数建议保留。Redis 如果本地没设密码password 留空字符串如果本机 Redis 开启了 requirepass必须在这里填写对应密码否则启动时没有报错但登录时验证码会一直转圈。日志路径在logback.xml里默认写到用户目录有些环境没有写权限就要改成项目内或/data/logs下。4.3 后端启动从 IDE 到命令行两种方式项目启动本质上就是启动 RuoYiApplication 这个 Spring Boot 主类。# 在 IDEA 里直接运行 RuoYiApplication 的 main 方法 # 或者用 Maven 命令在项目根目录启动 mvn spring-boot:run后端默认端口在 application.yml 里查看通常是 8080。启动日志里看到Started RuoYiApplication才算启动成功。如果报Port 8080 was already in use说明端口被别的进程占用改掉server.port或者把占用进程杀掉即可。日志里出现Connection refused: connect时90% 的原因是 Redis 没有启动去 Redis 安装目录执行redis-server redis.conf把服务拉起来再看。4.4 前端启动npm install 的版本账要提前算好前端部分以 RuoYi-Vue 为例默认是 Vue2 项目。进入前端目录后依次执行安装和启动命令。npm install --registryhttps://registry.npmmirror.com npm run dev前端默认端口看vue.config.js里的 port 配置启动成功后浏览器打开对应地址用 admin/admin123 登录。RuoYi-Vue 这道项目对 Node 版本很敏感Node 17 及以上版本跑 webpack4 经常报digital envelope routines::unsupported这类错误建议直接使用 Node 16 的稳定版本。若依 Vue3 TypeScript 版本如果启动时疯狂报类型错误多半是安装依赖时 lock 文件与当前 Node 版本不匹配删掉 node_modules 和 package-lock.json 后重新安装通常能解决。4.5 前后端联调的最后一公里代理配置登录页出现的“请求失败”绝大多数不是后端接口写错了而是前端没有把/dev-api开头的请求代理到后端端口。RuoYi-Vue 在vue.config.js里配置代理module.exports { devServer: { host: 0.0.0.0, port: 80, proxy: { /dev-api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/dev-api: } } } } }/dev-api是若依前端统一的前缀后端接口实际路径不含这个前缀代理时要用pathRewrite把它去掉。看到 Network 面板里有GET /dev-api/captchaImage返回 200 并且有 JSON 数据说明代理链路已经通了。如果要上服务器部署用宝塔面板的话就是改四个位置后端 jar 包用java -jar启动、前端执行npm run build:prod把 dist 目录交给 Nginx、MySQL 和 Redis 地址改成服务器内网或公网真实地址、Nginx 里加一条 location 把/prod-api/代理到后端端口。5. 避坑指南若依仓库系统最常见的五个翻车现场与排查思路5.1 登录页验证码一直转圈先怀疑 Redis 而不是代码现象验证码图片不出来或者转几秒后页面提示“验证码获取失败”后端日志没有明显异常启动也算成功。原因若依的验证码是生成后存到 Redis 的登录接口再从 Redis 里取出来校验。Redis 没启动、密码配置不一致、Redis 端口被占用都会导致这个环节静默失败。解决先确认本机 Redis 进程存在执行redis-cli ping能返回 PONG再到application.yml里检查 redis 密码是否与 redis.conf 里的requirepass一致最后清除浏览器缓存重试。这个坑能排在我的避坑清单第一位是因为它表面上看像前端问题实际原因永远在后端依赖。我一般会在启动项目前先把 Redis 拉起来再动代码。5.2 菜单导入后左侧不显示parent_id 和角色分配两个方向排查现象代码生成器生成的菜单 SQL 执行成功sys_menu 表里也能查到记录但登录后左侧菜单看不到仓库管理这一项。原因一个是子菜单的 parent_id 没有指向当前顶级目录而是写成了 0 或 1导致菜单分散在别的根节点下另一个是角色没有关联新菜单sys_role_menu 表里没有对应记录用户登录后菜单树压根不会查出来。解决执行菜单 SQL 之后用下面这条 SQL 检查新菜单的 parent_id 是否存在且层级正确SELECT menu_id, menu_name, parent_id, menu_type, perms FROM sys_menu WHERE menu_name LIKE %仓库% OR menu_name LIKE %入库%;如果查出 parent_id 是 0 且 menu_type 是 C说明页面菜单被挂成了顶级菜单必须改回目录菜单下面。同时去“系统管理 - 角色管理”里给当前角色重新分配一次菜单保存后再刷新页面。注意若依的菜单是走缓存的改完仍然不生效时重启后端或者清一次 Redis。5.3 自定义统计 SQL 查出来的数据莫名其妙变少数据权限在暗中过滤现象写了一个“按仓库汇总当前库存”的 SQL自己在本机数据库里执行结果有 20 行放到若依系统里查出来只剩 5 行或者完全为空。原因若依的DataScope注解会让系统根据当前登录用户所属部门自动拼接数据权限过滤条件这只对包含 dept 字段的表生效但如果你把统计 SQL 里取了别名且过滤条件拼到了错误的表别名上就会出现结果集被“无差别过滤”的情况。解决确认这个查询是否需要按部门隔离数据。仓库库存是全局概念一般不需要部门级隔离把 Controller 或 Service 上的DataScope注解去掉即可如果确实需要就确保统计主表的别名是 dept 表关联的别名并且 SELECT 里显式带出 dept_id 字段。这个注解的作用机制是若依源码里非常经典的一块也常被拿来当 Java 面试题问你“数据权限和菜单权限的区别”建议动手读一下DataScopeAspect的源码。5.4 前端 npm run dev 直接红字绝大多数是 Node 版本背锅现象RuoYi-Vue 执行npm run dev报digital envelope routines::unsupported或者 RuoYi-Plus 的 Vue3 TypeScript 项目报一堆类型错误甚至 node_modules 一装就卡死。原因RuoYi-Vue 用的是 webpack4Node 17 及以上版本启用了新版本 OpenSSL执行哈希算法时和 webpack4 不兼容RuoYi-Plus 则对 Node 和 pnpm 版本有明确配对要求版本错位时 lock 文件解析出来的依赖树不一致。解决RuoYi-Vue 最省心的方案是安装 Node 16 并锁定大版本或者在启动命令前加NODE_OPTIONS--openssl-legacy-providerRuoYi-Plus 项目先看根目录有没有.npmrc或packageManager字段照着指定版本装。如果已经报错删掉 node_modules、package-lock.json用npm cache clean --force清一次缓存再重装。不要盲目升级依赖版本尤其是 webpack 和 vue-tsc 这类底层依赖升一个版本可能带出连锁报错。5.5 后端起不来提示 mapper 绑定异常生成代码没放到扫描路径现象启动报org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.ruoyi.wms.mapper.WmsInboundMapper.selectWmsInboundList。原因代码生成器输出的 XML 文件放到了错误的目录或者 Mapper 接口被扫描到但 XML 没被 MyBatis 加载常见于把生成的代码复制到若依工程时包路径没有保持com.ruoyi.wms.mapper一致。解决打开编译后的 target 目录检查WmsInboundMapper.xml是否存在且与接口同包确认application.yml里 MyBatis 的 mapperLocations 配置覆盖了classpath*:mapper/**/*Mapper.xml如果 XML 文件在 src 下但 IDEA 没有自动编译资源需要在 pom.xml 里把src/main/java下的 xml 也纳入资源目录。每次生成代码后建议先重新编译一遍再启动避免出现“代码已生成但没编译进 target”这种看起来很玄学的问题。6. 让仓库系统再往前走一步用生成器过一遍全流程再用一条 SQL 验收库存链路仓库管理系统跑通以后建议再干一件事用代码生成器把 wms_stock 表也完整生成一遍不直接改代码而是对照生成出来的文件把 Domain、Mapper、Service、Controller、Vue 五个层级的输出物依次看一遍。这样做的目的不是重复造轮子而是让你能说出“这一层是做什么的、改库存要动哪一层”这个经典问题。Domain 里的字段与表结构一一对应Mapper 接口是数据库操作的入口Service 里写事务和过账逻辑Controller 只负责接参数并返回给前端Vue 页面是我们的操作界面。这套链路搞清楚了答辩时就等于有了一张完整的技术地图。然后做一次手工验收。在页面上创建一张入库单添加两个物料分别填数量和单价提交并过账。过账后查库存表SELECT p.product_code, p.product_name, s.quantity, s.locked_quantity FROM wms_stock s LEFT JOIN wms_product p ON s.product_id p.id ORDER BY p.product_code;如果库存数量与入库单明细数量一致说明过账逻辑的事务生效了如果库存没变优先检查 Service 层过账方法上有没有Transactional以及库存写入是不是在明细循环里做了重复赋值。再创建一张出库单把数量扣成负数或扣到低于锁定量系统必须给出提示而不是直接保存这一步能验出库存校验逻辑是否完整。答辩时讲好一条业务链路比罗列十个功能更有说服力创建入库单单据状态为草稿点击审核系统在事务里校验物料、更新库存、把状态改为已过账出库同理只是扣减库存并校验库存充足。整条链路讲明白再顺带说一句“库存不足时抛出异常事务回滚数据库不会出现脏数据”这话一出来相当于一场项目实战版的 Java 面试。我自己做这类项目时也翻过车改菜单 SQL 之前没做备份把一批子菜单的 parent_id 全部误写成 0整个菜单树变成了几棵并行树登录进去什么都点不开最后对着 pym 导出的 sys_menu 一条条恢复浪费了一整个晚上。后来养成的习惯是每次动手改菜单、角色、SQL 脚本前先用一条mysqldump把这三张表导出来放到项目目录下再操作。一个小备份动作而已但它救过我很多次。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑