17 KiB
decision_manage(决策管理)模块 — 数据库表字段详解
概述
decision_manage 模块涉及两张核心数据库表:
st_strategy_config(仓储策略配置表):定义每个具体策略的元信息和运行参数st_sect_strategy(库区策略关联表):定义每个库区绑定了哪些策略,形成策略链
两张表通过 strategy_code(策略编码)字段产生逻辑关联——st_sect_strategy.strategy 中存储的 JSON 数组元素值,对应 st_strategy_config.strategy_code。
一、st_strategy_config(仓储策略配置表)
作用:存储每一个可用策略的完整定义,包括策略的基本信息、分类、运行参数和启用状态。每个策略对应一个 Spring Bean(继承 Decisioner 的处理器),系统启动时通过 strategy_code 与 Bean 名称自动关联。
字段详解
1. id — 策略标识(主键)
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
| 主键策略 | 无自增,手动赋值 |
| 生成方式 | IdUtil.getStringId()(雪花ID或UUID变体) |
作用:策略记录的唯一标识,由后端在新增时自动生成,前端不感知。create 方法中通过 IdUtil.getStringId() 赋值。
2. strategy_code — 策略编码
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR(64) |
作用:策略的编码标识,是两张表之间的核心关联字段。每个策略编码与 Spring 容器中一个 Decisioner 子类的 @Service("xxx") Bean 名称严格一一对应。
取值示例:
| 策略编码 | 对应处理器 | 分类 |
|---|---|---|
fifo |
FIFORuleHandler | base |
nearby |
NearbyRuleHandler | base |
weight |
WeightRuleHandler | base |
cluster |
ClusterRuleHandler | base |
limitStorage |
LimitStorageRuleHandler | base |
alleyAve |
AlleyAveRuleHandler | base |
depthPriority |
DepthPriorityHandler | diy |
fifo2 |
FIFO2RuleHandler | diy |
inventory |
InventoryRuleHandler | diy |
passRCL |
PassRCLHandler | diy |
注意:当前 create 方法中硬编码为 "000",这意味着新增策略时需要在数据库中手动修正 strategy_code 的值,或在界面上提供修改入口。这是一个应改进的点。
关联关系:被 st_sect_strategy.strategy JSON 数组引用,也被 Decisioner.afterPropertiesSet() 用于查询自身配置。
3. strategy_name — 策略名称
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:策略的中文显示名称,用于后台管理界面展示,如"先进先出"、"就近放置"、"巷道均衡"等。
约束:create 方法中会校验名称唯一性——如果已存在相同名称的策略,抛出 BadRequestException("已存在相同名称的策略【xxx】")。
使用场景:在 GET /api/strategy/decisionColumns 接口中作为下拉选项的 label 字段返回给前端。
4. strategy_type — 策略类型
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:标识策略适用于哪种仓储操作场景。
取值约定:
| 值 | 含义 | 典型策略 |
|---|---|---|
1 |
入库策略 | limitStorage, nearby, alleyAve, weight, cluster, depthPriority, inventory |
2 |
出库策略 | fifo, fifo2 |
3 |
通用策略(出入库均可) | alleyAve(同时支持出入) |
使用场景:上层调度模块根据当前任务是入库还是出库,筛选对应类型的策略进行链式调用。
5. class_type — 类处理类型
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:标识策略实现类的归属分类,用于前端分组展示或权限控制。
取值约定:
| 值 | 含义 | 说明 |
|---|---|---|
base |
基础策略 | 通用性强的标准策略,如 FIFO、就近、限位、均衡等 |
diy |
自定义策略 | 为特定项目/现场定制的策略,如深位优先、双叉分配等 |
代码中的实际使用:当前在 Java 代码中未发现直接使用该字段做业务逻辑判断,主要用于界面上的分类筛选和展示。
6. param — 策略参数
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR(存储 JSON 字符串) |
作用:策略运行时可配置的参数,以 JSON 字符串形式存储。这是策略配置最核心的字段,直接影响策略的执行行为。
各策略的 param 格式与含义:
| 策略 | param 格式 | 含义 |
|---|---|---|
| alleyAve (巷道均衡) | ["x","z","y"] |
排序优先级:先按排(x),再按层(z),最后按列(y) |
| limitStorage (货位限位) | ["h","w","l","weight"] |
需要匹配的维度:高度、宽度、深度、承重 |
| passRCL (排/列/层过滤) | {"y":[1,2,3,104,103,102]} |
排除列号为 1,2,3,102,103,104 的货位 |
| nearby (就近放置) | 当前未使用 param | 使用硬编码的 Top10,可扩展为从 param 读取候选数量 |
| weight (轻上重下) | 通过 handler 参数传递 | 泛型声明为 String,实际解析为 JSON |
注意:同一策略类可以在 st_strategy_config 中存在多条记录(不同 strategy_code),每条记录配置不同的 param,实现同一策略逻辑在不同场景下的差异化复用。例如不同库区可以有不同的排序维度。
7. form_data — 策略表单配置
| 属性 | 说明 |
|---|---|
| Java 类型 | JSONObject |
| 数据库类型 | VARCHAR(通过 FastjsonSortTypeHandler 序列化) |
| 默认值 | new JSONObject()(空 JSON 对象) |
| TypeHandler | FastjsonSortTypeHandler.class |
作用:存储策略在前端表单中的渲染配置,例如表单字段定义、校验规则、下拉选项等。这是一个纯前端辅助字段,不参与后端决策逻辑。
示例:可能包含类似以下结构的数据(具体格式取决于前端表单设计器):
{
"fields": [
{"name": "x", "label": "排", "type": "checkbox"},
{"name": "y", "label": "列", "type": "checkbox"},
{"name": "z", "label": "层", "type": "checkbox"}
]
}
与 param 的区别:
param:策略的运行参数,后端handler()方法中解析并使用form_data:策略的表单配置,前端渲染配置界面时使用
8. remark — 描述/备注
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:策略的补充说明文本,用于记录策略的用途、注意事项、变更历史等。纯展示字段,不参与业务逻辑。
9. is_used — 是否启用
| 属性 | 说明 |
|---|---|
| Java 类型 | Boolean |
| 数据库类型 | TINYINT 或 BIT |
| 默认值 | null(未设置,建议默认为 true 或 false) |
作用:控制策略的启用/禁用状态。只有启用的策略才会在策略链中被调用。提供 PUT /api/strategy/changeActive 接口进行切换。
切换逻辑(changeActive 方法):每次调用将 is_used 值取反,实现一键启用/禁用切换。
与 ban 的区别:is_used 是实际在使用的启用状态控制字段;ban 字段在代码中未被使用,疑似冗余。
10. ban — 是否禁用
| 属性 | 说明 |
|---|---|
| Java 类型 | Boolean |
| 数据库类型 | TINYINT 或 BIT |
作用:从命名推断用于禁用标记,但在当前 Java 代码中未找到任何读写该字段的逻辑。可能是早期设计预留的字段,后来被 is_used 替代,或者是数据库中有但代码中未同步使用。
建议:确认是否在 SQL 脚本或前端有使用,如果确认废弃则应清理。
11. update_name — 修改人名称
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:记录最后一次修改该策略配置的操作人姓名。在 update、deleteAll、changeActive 方法中通过 SecurityUtils.getCurrentNickName() 自动赋值。
12. update_time — 修改时间
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:记录最后一次修改的时间戳。在 update、deleteAll、changeActive 方法中通过 DateUtil.now() 自动赋值。
注意:使用 String 而非 LocalDateTime 或 Date,实际存储格式取决于 DateUtil.now() 的返回值(通常是 yyyy-MM-dd HH:mm:ss)。
13. is_delete — 是否删除(逻辑删除标记)
| 属性 | 说明 |
|---|---|
| Java 类型 | Boolean |
| 数据库类型 | TINYINT 或 BIT |
| 查询默认值 | Boolean.FALSE(在 StrategyQuery 中设置) |
作用:逻辑删除标记。删除策略时不会物理删除记录,而是将该字段设为 "1"(注意代码中使用字符串 "1" 而非布尔值 true,存在类型不一致)。
使用方式:
- 查询时:Mapper XML 中硬编码过滤条件
is_delete = "0",只查询未删除记录 - 删除时:
deleteAll方法通过UpdateWrapper设置is_delete = "1"
注意:StrategyQuery 中虽然设置了 is_delete = Boolean.FALSE 作为默认参数,但 Mapper XML 中直接硬编码了 is_delete = "0",Query 对象中的 is_delete 实际上没有在 SQL 中被引用。
二、st_sect_strategy(库区策略关联表)
作用:定义每个库区与策略链的绑定关系。一个库区可以绑定多个策略,这些策略按数组顺序组成策略链,入库/出库时依次执行。
字段详解
1. id — 主键
| 属性 | 说明 |
|---|---|
| Java 类型 | Integer |
| 数据库类型 | INT |
| 主键策略 | IdType.AUTO(数据库自增) |
作用:记录的唯一标识,由数据库自动生成。
2. sect_code — 库区编码
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:标识该策略链配置属于哪个库区。库区是仓库物理空间的逻辑划分,每个库区有独立的编码(如 A01、B02 等)。
使用场景:
- 调度模块接到入库/出库任务时,根据目标库区编码查询该库区绑定的策略链
SectStrategyQuery支持按sect_code过滤分页查询
关联:库区编码对应基础数据模块中库区/仓位主数据,本表不存储库区本身的详细信息。
3. strategy — 策略编码列表(策略链)
| 属性 | 说明 |
|---|---|
| Java 类型 | List<String> |
| 数据库类型 | VARCHAR(存储 JSON 数组字符串) |
| TypeHandler | ListStrTypeHandler.class |
作用:这是决策模块最核心的字段,定义了该库区的策略链——即入库/出库时依次执行的策略编码列表,数组顺序即为执行顺序。
存储格式(数据库中的实际内容):
["limitStorage", "nearby", "alleyAve"]
Java 中的表示:
List<String> strategy = ["limitStorage", "nearby", "alleyAve"]
执行流程:当任务到达该库区时,调度模块会按数组顺序依次调用对应的策略处理器:
可用货位列表
→ limitStorage.handler() // 过滤尺寸/重量不匹配的货位
→ nearby.handler() // 按距离排序,取前N个
→ alleyAve.handler() // 巷道均衡分配
→ 最终货位列表
TypeHandler 转换机制:
- 写入时(Java → DB):
ListStrTypeHandler.setNonNullParameter()调用JSON.toJSONString(parameter),将List<String>序列化为 JSON 数组字符串 - 读取时(DB → Java):
ListTypeHandler.getNullableResult()调用JSONArray.parseArray(s, String.class),将 JSON 数组反序列化为List<String>;若为NULL则返回空ArrayList
策略编码的取值:列表中的每个元素必须是 st_strategy_config.strategy_code 的有效值,对应一个已注册的 Spring Bean。如果填写了不存在的策略编码,运行时才会报错。
4. strategy_type — 策略类型
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:标识该条策略链配置适用于哪种操作场景。
取值约定:
| 值 | 含义 |
|---|---|
1 |
入库策略链 |
2 |
出库策略链 |
使用场景:一个库区可能同时需要入库和出库的策略链配置,通过该字段区分。例如:
库区 A01:
- strategy_type=1: ["limitStorage", "nearby", "alleyAve"] ← 入库用
- strategy_type=2: ["fifo"] ← 出库用
调度模块根据当前任务是入库还是出库,查询对应 strategy_type 的策略链。
5. description — 描述
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:对该库区策略链配置的说明文本,用于后台管理界面的展示。纯文本备注,不参与业务逻辑。
6. update_time — 更新时间
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:记录最后一次修改的时间。在 Controller 的 create 和 update 方法中通过 DateUtil.now() 手动赋值。
7. update_name — 更新人
| 属性 | 说明 |
|---|---|
| Java 类型 | String |
| 数据库类型 | VARCHAR |
作用:记录最后一次修改该库区策略配置的操作人。在 Controller 中通过 SecurityUtils.getCurrentUsername() 手动赋值。
三、两表关联关系
st_strategy_config (策略定义) st_sect_strategy (库区-策略绑定)
┌──────────────────────────┐ ┌──────────────────────────┐
│ id (PK) │ │ id (PK, AUTO) │
│ strategy_code ◄──────────┼──────────│ strategy (JSON数组) │
│ strategy_name │ 逻辑引用 │ sect_code │
│ strategy_type │ │ strategy_type │
│ class_type │ │ description │
│ param │ │ update_time │
│ form_data │ │ update_name │
│ remark │ └──────────────────────────┘
│ is_used │
│ ban │
│ update_name │
│ update_time │
│ is_delete │
└──────────────────────────┘
关联方式:st_sect_strategy.strategy 中的 JSON 数组元素(如 "fifo")逻辑上引用 st_strategy_config.strategy_code。
当前限制:由于使用 JSON 数组存储,数据库层面无法建立外键约束。如果策略编码被修改或删除,库区策略链中的引用不会自动更新或校验。
查询链路:
- 调度模块根据任务中的库区编码
sect_code+ 策略类型strategy_type查询st_sect_strategy - 从
strategy字段解析出策略编码列表 - 按顺序从 Spring 容器中获取对应 Bean 名称的
Decisioner实例 - 每个
Decisioner在初始化时已通过strategy_code从st_strategy_config加载了自身的配置(param、form_data等)
四、字段补充说明
缺失的常见字段
两张表均没有明确声明以下常见审计字段(但代码中有隐式引用):
| 缺失字段 | 说明 |
|---|---|
create_time |
创建时间 — 实体中未声明,但 StStrategyConfigServiceImpl.pageQuery 中使用了 ORDER BY create_time DESC,说明数据库表中实际存在该字段,只是 Java 实体未映射 |
create_name |
创建人 — 新增方法中未赋值,可能依赖数据库默认值 |
类型不一致问题
| 问题 | 位置 | 详情 |
|---|---|---|
is_delete 赋值类型 |
StStrategyConfigServiceImpl.deleteAll() |
Boolean 字段被赋值为字符串 "1" |
update_time 类型 |
两张表 | 使用 String 存储时间,而非 LocalDateTime |
五、设计改进建议(与字段相关)
-
strategy_code创建时硬编码"000":create方法未提供策略编码的输入入口,需要后续手动修改。建议在创建界面提供编码输入框,并增加编码唯一性校验。 -
ban字段废弃:代码中未使用,确认后可清理。 -
is_delete赋值类型修复:deleteAll中应将"1"改为true,保持与字段声明的Boolean类型一致。 -
update_time使用更合适的类型:建议从String改为LocalDateTime,利用 Java 8 时间 API 的类型安全优势。 -
补充
create_time/create_name映射:数据库存在但 Java 实体未映射,导致新增记录时无法在实体层面追踪创建信息。 -
strategyJSON 数组的引用完整性:无法通过数据库约束保证st_sect_strategy.strategy中的策略编码在st_strategy_config中真实存在,建议在保存时增加后端校验逻辑。