Files
huachuang/决策管理模块-数据库表字段分析.md
2026-07-18 17:38:34 +08:00

452 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` |
**作用**:存储策略在前端表单中的渲染配置,例如表单字段定义、校验规则、下拉选项等。这是一个**纯前端辅助字段**,不参与后端决策逻辑。
**示例**:可能包含类似以下结构的数据(具体格式取决于前端表单设计器):
```json
{
"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` |
**作用**:这是决策模块最核心的字段,定义了该库区的**策略链**——即入库/出库时依次执行的策略编码列表,**数组顺序即为执行顺序**。
**存储格式**(数据库中的实际内容):
```json
["limitStorage", "nearby", "alleyAve"]
```
**Java 中的表示**
```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 数组存储,数据库层面无法建立外键约束。如果策略编码被修改或删除,库区策略链中的引用不会自动更新或校验。
**查询链路**
1. 调度模块根据任务中的库区编码 `sect_code` + 策略类型 `strategy_type` 查询 `st_sect_strategy`
2.`strategy` 字段解析出策略编码列表
3. 按顺序从 Spring 容器中获取对应 Bean 名称的 `Decisioner` 实例
4. 每个 `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` |
---
## 五、设计改进建议(与字段相关)
1. **`strategy_code` 创建时硬编码 `"000"`**`create` 方法未提供策略编码的输入入口,需要后续手动修改。建议在创建界面提供编码输入框,并增加编码唯一性校验。
2. **`ban` 字段废弃**:代码中未使用,确认后可清理。
3. **`is_delete` 赋值类型修复**`deleteAll` 中应将 `"1"` 改为 `true`,保持与字段声明的 `Boolean` 类型一致。
4. **`update_time` 使用更合适的类型**:建议从 `String` 改为 `LocalDateTime`,利用 Java 8 时间 API 的类型安全优势。
5. **补充 `create_time` / `create_name` 映射**:数据库存在但 Java 实体未映射,导致新增记录时无法在实体层面追踪创建信息。
6. **`strategy` JSON 数组的引用完整性**:无法通过数据库约束保证 `st_sect_strategy.strategy` 中的策略编码在 `st_strategy_config` 中真实存在,建议在保存时增加后端校验逻辑。