从“用框架”到“控系统”——业务模型和技术模型之间的映射
什么是业务模型和技术模型?
业务模型(Business Model)
- 定义:业务模型描述了现实世界中的业务实体、流程和规则,通常从业务需求和用户的角度出发。它是业务逻辑的抽象,关注**“做什么”**,而不关心技术实现。
- 特点:
- 反映业务领域的概念,如“库存设备”、“项目设备”、“存放位置”、“新制件数量”。
- 使用业务术语,如
location
(存放位置)、useLife
(使用年限)、totalQuantity
(总数量)。 - 由业务分析师、产品经理或领域专家定义。
- 例子(MES 系统):
- 实体:库存设备(
biz_inventory_equipment
)、项目设备(biz_project_equipment
)。 - 流程:按
location
统计库存总量,按useLife
计算新制件数量(sgrpReceiveQuantity + totalQuantity
)。 - 规则:过滤
equipmentClass = 20
或source = 'SGRP'
。
- 实体:库存设备(
技术模型(Technical Model)
- 定义:技术模型是将业务模型转化为可实现的技术结构,关注**“如何做”**,包括数据库表、类、API、界面组件等。它是业务模型的技术表达。
- 特点:
- 使用技术术语,如表名(
biz_inventory_equipment
)、类名(BizInventoryEquipmentVo
)、API 路径(/listWithGroup
)。 - 涉及代码、数据库设计、前端组件等。
- 由开发者和技术架构师定义。
- 使用技术术语,如表名(
- 例子(MES 系统):
- 数据库表:
biz_inventory_equipment
(字段location
,total_quantity
)。 - Java 类:
BizInventoryEquipmentDto
(输入过滤条件)、BizInventoryEquipmentVo
(输出数据)。 - API:
/bizInventoryEquipment/listWithGroup
。 - 前端组件:
formStorageQuantity.vue
的bar-chart
和table-box
。
- 数据库表:
映射关系
- 业务模型到技术模型的映射是将业务需求(实体、流程、规则)转化为技术实现(代码、数据库、接口)。
- 目标:确保技术模型准确反映业务需求,同时保持代码的可维护性、可扩展性。
- 过程:通过分析业务需求,设计对应的技术结构(如类、表、API),并定义数据和逻辑的转换规则。
业务模型与技术模型的映射过程
以下是映射的关键步骤,结合 MES 系统说明:
-
识别业务实体和属性
- 业务模型:确定核心业务实体和它们的属性。
- 实体:库存设备(
Inventory Equipment
)。 - 属性:存放位置(
location
)、总数量(totalQuantity
)、使用年限(useLife
)。
- 实体:库存设备(
- 技术模型:映射到数据库表和 Java 类。
- 表:
biz_inventory_equipment
(字段:location
,total_quantity
,use_life
)。 - 类:
BizInventoryEquipment
(实体类)、BizInventoryEquipmentVo
(输出 DTO)。
- 表:
- 业务模型:确定核心业务实体和它们的属性。
-
定义业务流程
- 业务模型:描述业务操作和规则。
- 流程:按
location
分组统计totalQuantity
的总和。 - 规则:只统计未删除的记录(
del_flag = 0
)。
- 流程:按
- 技术模型:映射到 API 和 SQL 查询。
- API:
@PostMapping("/listWithGroup")
。 - SQL:
<select id="getGroupedBizInventoryEquipmentList" resultMap="BaseResultMap">SELECT location, SUM(total_quantity) AS totalQuantitySumFROM biz_inventory_equipmentWHERE del_flag = 0GROUP BY location </select>
- API:
- 业务模型:描述业务操作和规则。
-
设计用户交互
- 业务模型:用户需要通过界面输入过滤条件,查看统计结果。
- 交互:用户选择
locationFilter
,点击“搜索”,查看柱状图和表格。
- 交互:用户选择
- 技术模型:映射到前端组件和 API 调用。
- 组件:
formStorageQuantity.vue
的<el-select v-model="formFilter.locationFilter">
。 - API 调用:
const res = await BizInventoryEquipmentController.listWithGroup(this, {groupParam: [{ fieldName: 'location' }],aggregateParam: [{ fieldName: 'totalQuantity', aggregateType: 'sum', alias: 'totalQuantitySum' }],bizInventoryEquipmentDtoFilter: { location: this.formFilter.locationFilter } });
- 组件:
- 业务模型:用户需要通过界面输入过滤条件,查看统计结果。
-
数据转换和呈现
- 业务模型:用户希望看到直观的统计结果(如
locationName
而非location
ID)。 - 技术模型:前端处理数据,映射 ID 到名称。
- 前端:调用
DictionaryController.dictGlobalDict
获取locationName
。 - 代码:
this.chartData = res.data.dataList.map(item => ({location: item.location,totalQuantitySum: item.totalQuantitySum || 0,locationName: locationMap[item.location] || item.location }));
- 前端:调用
- 业务模型:用户希望看到直观的统计结果(如
MES 项目中的映射示例
以下以 formStorageQuantity.vue
和 formNewManufacture.vue
为例,展示业务模型到技术模型的映射。
示例 1:formStorageQuantity.vue
(库存统计)
- 业务模型:
- 实体:库存设备(
Inventory Equipment
)。 - 属性:存放位置(
location
)、总数量(totalQuantity
)。 - 流程:按
location
分组,计算totalQuantity
总和,显示为柱状图。 - 规则:支持过滤特定
location
,显示对应的locationName
。
- 实体:库存设备(
- 技术模型:
- 数据库表:
biz_inventory_equipment
(字段:location
,total_quantity
,del_flag
)。 - Java 类:
BizInventoryEquipmentDto
:输入过滤条件(如location
)。BizInventoryEquipmentVo
:输出数据(如location
,totalQuantitySum
)。
- API:
/bizInventoryEquipment/listWithGroup
。@PostMapping("/listWithGroup") public ResponseResult<MyPageData<BizInventoryEquipmentVo>> listWithGroup(@MyRequestBody BizInventoryEquipmentDto bizInventoryEquipmentDtoFilter,@MyRequestBody(required = true) MyGroupParam groupParam,@MyRequestBody MyOrderParam orderParam,@MyRequestBody MyPageParam pageParam) {// ... }
- SQL:
<select id="getGroupedBizInventoryEquipmentList" resultMap="BaseResultMap">SELECT location, SUM(total_quantity) AS totalQuantitySumFROM biz_inventory_equipmentWHERE del_flag = 0<if test="filter.location != null">AND location = #{filter.location}</if>GROUP BY location </select>
- 前端:
formStorageQuantity.vue
。- 输入:
<el-select v-model="formFilter.locationFilter">
。 - 输出:
bar-chart
显示locationName
和totalQuantitySum
。
- 输入:
- 数据库表:
映射过程:
- 实体映射:
Inventory Equipment
→biz_inventory_equipment
表。 - 属性映射:
location
→biz_inventory_equipment.location
,totalQuantity
→SUM(total_quantity)
。 - 流程映射:分组统计 →
/listWithGroup
API 和 SQLGROUP BY location
。 - 交互映射:用户选择
locationFilter
→formFilter.locationFilter
→ API 参数bizInventoryEquipmentDtoFilter.location
。
示例 2:formNewManufacture.vue
(新制件统计)
- 业务模型:
- 实体:项目设备(
Project Equipment
)、库存设备(Inventory Equipment
)。 - 属性:
- A:
source = 'SGRP'
的sgrpReceiveQuantity
(项目设备)。 - B:
equipmentClass = 20
的totalQuantity
(库存设备)。 - 新制件数量 = A + B,按
useLife
分组。
- A:
- 流程:统计 A 和 B,合并后按
useLife
显示柱状图。 - 规则:支持
useLife
范围过滤(如 1-5 年)。
- 实体:项目设备(
- 技术模型:
- 数据库表:
biz_project_equipment
(字段:source
,sgrp_receive_quantity
,equipment_number
)。biz_inventory_equipment
(字段:use_life
,total_quantity
,equipment_class
)。
- Java 类:
BizProjectEquipmentDto
:过滤source = 'SGRP'
。BizInventoryEquipmentDto
:过滤equipmentClass = 20
。NewManufactureVo
(建议新增):输出useLife
和newManufactureQuantity
。
- API(优化后):
/newManufacture/aggregate
。@PostMapping("/aggregate") public ResponseResult<List<NewManufactureVo>> aggregate(@RequestBody NewManufactureDto dto) {// 合并 A 和 B 的查询逻辑 }
- SQL:
<!-- BizProjectEquipmentMapper.xml --> <select id="getGroupedBizProjectEquipmentList" resultType="com.management.webadmin.app.model.BizProjectEquipmentVo">SELECT bie.use_life AS useLife, SUM(bpe.sgrp_receive_quantity) AS sgrpReceiveQuantitySumFROM biz_project_equipment bpeJOIN biz_inventory_equipment bie ON bpe.equipment_number = bie.equipment_numberWHERE bpe.source = 'SGRP' AND bpe.del_flag = 0<if test="filter.useLifeStart != null">AND bie.use_life >= #{filter.useLifeStart}</if>GROUP BY bie.use_life </select>
- 前端:
formNewManufacture.vue
。- 输入:
<input-number-range v-model="formFilter.useLifeFilter">
。 - 输出:
bar-chart
显示useLife
和newManufactureQuantity
。
- 输入:
- 数据库表:
映射过程:
- 实体映射:
Project Equipment
→biz_project_equipment
,Inventory Equipment
→biz_inventory_equipment
。 - 属性映射:
sgrpReceiveQuantity
→SUM(bpe.sgrp_receive_quantity)
。totalQuantity
→SUM(bie.total_quantity)
。useLife
→bie.use_life
。
- 流程映射:合并 A + B →
/newManufacture/aggregate
API,合并前端chartData
。 - 交互映射:用户输入
useLifeFilter
→ API 参数useLifeStart
和useLifeEnd
。
如何优化映射
在MES 项目中,优化业务模型与技术模型的映射可以提高开发效率和系统性能。以下是具体建议:
-
清晰定义业务模型
- 与业务人员沟通,明确实体、属性和规则。
- 例:确认
newManufactureQuantity
的计算规则(A + B),确保useLife
的单位一致(年)。 - 工具:使用 UML 类图或 ER 图表示业务实体和关系。
-
设计简洁的技术模型
- DTO 和 VO:为每个业务流程设计专用 DTO(如
NewManufactureDto
)和 VO(如NewManufactureVo
),避免返回冗余字段。public class NewManufactureVo {private Double useLife; // 映射业务属性 useLifeprivate Long newManufactureQuantity; // 映射 A + B// Getters and Setters }
- API 合并:如前文优化,将
formNewManufacture.vue
的两次 API 调用合并为/newManufacture/aggregate
。
- DTO 和 VO:为每个业务流程设计专用 DTO(如
-
保持映射一致性
- 命名规范:业务术语和技术字段保持一致,如
location
(业务)→location
(表字段/VO 属性)。 - 校验规则:在 DTO 中添加校验注解,确保输入符合业务规则。
public class BizInventoryEquipmentDto {@NotBlankprivate String location;@Range(min = 0, max = 100)private Double useLifeStart;// ... }
- 命名规范:业务术语和技术字段保持一致,如
-
自动化映射
- 使用工具(如 MapStruct)自动映射业务实体和技术模型。
@Mapper public interface BizInventoryEquipmentMapper {BizInventoryEquipmentVo toVo(BizInventoryEquipment entity);List<BizInventoryEquipmentVo> toVoList(List<BizInventoryEquipment> entities); }
- 减少手动
MyModelUtil.copyTo
的代码,提高开发效率。
- 使用工具(如 MapStruct)自动映射业务实体和技术模型。
-
优化数据流(结合前文)
- 缓存静态数据(如
locationName
),减少 API 调用。 - 使用异步查询(如
CompletableFuture
)加速后端处理。 - 精简返回数据,只传输必要字段。
- 缓存静态数据(如
练习:设计业务模型到技术模型的映射
任务:为 MES 系统中的“设备状态统计”功能设计映射,统计 biz_inventory_equipment
表中按 status
分组的设备数量。
-
业务模型:
- 实体:库存设备(
Inventory Equipment
)。 - 属性:状态(
status
)、设备数量(count
)。 - 流程:按
status
分组,统计设备数量,显示为饼图。 - 规则:只统计未删除记录(
del_flag = 0
)。
- 实体:库存设备(
-
技术模型:
- 表:
biz_inventory_equipment
(字段:status
,del_flag
)。 - API:
/bizInventoryEquipment/statusCount
。 - 前端:
formEquipmentStatus.vue
(新增组件,含饼图)。
- 表:
参考答案:
- 业务模型:
- 实体:
Inventory Equipment
。 - 属性:
status
(如 “正常”、“故障”)、count
(设备数量)。 - 流程:统计每种状态的设备数量,显示饼图。
- 实体:
- 技术模型:
- SQL:
<select id="getStatusCount" resultType="com.management.webadmin.app.model.StatusCountVo">SELECT status, COUNT(*) AS countFROM biz_inventory_equipmentWHERE del_flag = 0GROUP BY status </select>
- Java 类:
public class StatusCountVo {private String status;private Long count;// Getters and Setters }@RestController @RequestMapping("/bizInventoryEquipment") public class BizInventoryEquipmentController {@Autowiredprivate BizInventoryEquipmentService service;@SaCheckPermission("bizInventoryEquipment.view")@GetMapping("/statusCount")public ResponseResult<List<StatusCountVo>> statusCount() {List<StatusCountVo> result = service.getStatusCount();return ResponseResult.success(result);} }
- 前端(
formEquipmentStatus.vue
):<template><pie-chart :data="chartData" /> </template> <script> export default {data() {return {chartData: []};},methods: {async loadChartData() {try {const res = await BizInventoryEquipmentController.statusCount(this);this.chartData = res.data.map(item => ({status: item.status,count: item.count}));} catch (e) {console.error('加载状态统计失败', e);this.$message.error('加载状态统计失败');}}} }; </script>
- SQL:
映射分析:
- 实体映射:
Inventory Equipment
→biz_inventory_equipment
。 - 属性映射:
status
→status
,count
→COUNT(*)
。 - 流程映射:统计状态数量 →
/statusCount
API 和GROUP BY status
。 - 交互映射:饼图显示 →
pie-chart
组件渲染chartData
。
总结
- 业务模型:描述业务实体(
Inventory Equipment
)、属性(location
,useLife
)、流程(分组统计)、规则(过滤条件)。 - 技术模型:映射到数据库表(
biz_inventory_equipment
)、Java 类(BizInventoryEquipmentVo
)、API(/listWithGroup
)、前端组件(bar-chart
)。 - 映射过程:
- 识别业务实体和属性 → 映射到表和类。
- 定义业务流程 → 映射到 API 和 SQL。
- 设计用户交互 → 映射到前端组件和 API 调用。
- 数据转换和呈现 → 映射到 DTO/VO 和前端渲染。
- 优化建议:
- 使用专用 DTO/VO 精简数据。
- 自动化映射(如 MapStruct)。
- 缓存静态数据、异步查询、合并 API。
- 结合 MES 项目:
formStorageQuantity.vue
:locationFilter
→/listWithGroup
→chartData
。formNewManufacture.vue
:useLifeFilter
→/newManufacture/aggregate
→newManufactureQuantity
。