Activity使用介绍
一、先搞懂:为什么 Activiti 需要这么多表?
Activiti 的表本质是按 “流程生命周期” 和 “功能职责” 分类的,每类表只负责特定阶段的信息。比如:
- 运行时(
ACT_RU_*):记录当前正在执行的流程数据(如待办任务、变量),流程结束后自动清空(或保留少量标记); - 历史(
ACT_HI_*):记录已完成的流程数据(如历史任务、审批记录),用于审计和查询; - 静态配置(
ACT_RE_*):记录流程定义、表单、角色等静态数据(部署后基本不变); - 身份关联(
ACT_ID_*):记录用户、角色信息(通常会和业务系统的用户表关联)。
举例:一个报销单流程从发起→审批→结束,会涉及:
ACT_RE_PROCDEF(流程定义,只部署一次);ACT_RU_EXECUTION(运行时流程实例)、ACT_RU_TASK(待办任务);- 流程结束后,运行时表数据被清理,历史表
ACT_HI_PROCINST、ACT_HI_TASKINST会保留完整记录。
二、简化查询:抓住 “核心表” 和 “关联字段”,拒绝全表扫描
查询复杂的根源是 “不知道该查哪张表”+“不知道表之间如何关联”。解决办法是:只关注核心表,记住关键关联字段。
1. 核心表清单(日常开发 80% 场景只需要这 6 张)
| 表分类 | 核心表名 | 作用 | 核心关联字段(用于查询) |
|---|---|---|---|
| 运行时 | ACT_RU_EXECUTION | 流程实例(关联业务记录) | ID_(流程实例 ID)、BUSINESS_KEY_(业务主键) |
| 运行时 | ACT_RU_TASK | 待办任务 | PROC_INST_ID_(关联流程实例)、ASSIGNEE_(审核人) |
| 历史 | ACT_HI_PROCINST | 历史流程实例 | ID_(历史流程 ID)、BUSINESS_KEY_(业务主键) |
| 历史 | ACT_HI_TASKINST | 历史任务(已完成的审批记录) | PROC_INST_ID_(关联历史流程)、ASSIGNEE_(审核人) |
| 静态配置 | ACT_RE_PROCDEF | 流程定义(如 “报销单流程 V2.0”) | ID_(流程定义 ID)、KEY_(流程标识,如 “expense”) |
| 变量表 | ACT_RU_VARIABLE(运行时)、ACT_HI_VARINST(历史) | 流程变量(如报销金额、申请人) | PROC_INST_ID_(关联流程实例)、NAME_(变量名) |
2. 常见查询场景:用 “业务主键” 串联所有表
实际开发中,最常用的查询是 “通过业务主键(如报销单 ID
EXP_001)查流程信息”,核心关联逻辑如下:步骤 1:业务主键→流程实例 ID
业务主键(
业务主键(
BUSINESS_KEY_)存在于ACT_RU_EXECUTION(运行时)和ACT_HI_PROCINST(历史)中,通过它可以拿到PROC_INST_ID_(流程实例 ID):sql
-- 查运行中的流程实例ID SELECT PROC_INST_ID_ FROM ACT_RU_EXECUTION WHERE BUSINESS_KEY_ = 'EXP_001';
-- 查已结束的流程实例ID(历史)
SELECT ID_ AS PROC_INST_ID_ FROM ACT_HI_PROCINST WHERE BUSINESS_KEY_ = 'EXP_001';
步骤 2:流程实例 ID→任务信息(待办 / 历史)
拿到
拿到
PROC_INST_ID_后,关联任务表:sql
-- 查待办任务(运行时) SELECT ID_ AS TASK_ID, ASSIGNEE_ AS 审核人, NAME_ AS 任务名称 FROM ACT_RU_TASK WHERE PROC_INST_ID_ = 'PROC_001'; -- 流程实例ID
-- 查历史审批记录(已完成)
SELECT ID_ AS TASK_ID, ASSIGNEE_ AS 审核人, END_TIME_ AS 完成时间
FROM ACT_HI_TASKINST
WHERE PROC_INST_ID_ = 'PROC_001';
总结:查询的核心链路是:
(记住这个链路,80% 的查询场景都能解决)
业务主键(BUSINESS_KEY_)→ 流程实例ID(PROC_INST_ID_)→ 任务ID/审核人/变量(记住这个链路,80% 的查询场景都能解决)
三、简化删除:别手动删表!用 API 封装逻辑
删除复杂的根源是 “手动操作数据库”(容易漏删关联表,导致数据不一致)。实际上,Activiti 的 API 已经封装了删除逻辑,99% 的场景不需要直接操作表。
1. 核心删除 API(按场景选)
| 场景 | 推荐 API | 作用(自动处理关联表) |
|---|---|---|
| 删除运行中流程 | runtimeService.deleteProcessInstance(procInstId, 原因) | 自动删除ACT_RU_EXECUTION、ACT_RU_TASK、ACT_RU_VARIABLE等运行时表关联数据,同时更新历史表状态。 |
| 删除历史流程(彻底清) | historyService.deleteHistoricProcessInstance(procInstId) | 自动删除ACT_HI_PROCINST、ACT_HI_TASKINST、ACT_HI_VARINST等历史表数据。 |
| 删除流程定义(废弃) | repositoryService.deleteDeployment(deploymentId, true) | 删除部署的流程定义(ACT_RE_PROCDEF),并级联删除相关的运行时 / 历史数据(true表示级联)。 |
2. 为什么不能手动删表?
Activiti 的表之间有强关联(如
PROC_INST_ID_贯穿运行时和历史表),手动删表可能导致:- 漏删关联数据(如删了
ACT_RU_EXECUTION,但ACT_RU_TASK还残留,导致 “幽灵任务”); - 历史表状态不一致(如运行时流程已删,但历史表
END_TIME_未更新,查询时误以为流程还在运行)。
四、实用技巧:进一步降低复杂度
- 只记 “核心表”,忽略边缘表
日常开发中,ACT_RU_EXECUTION、ACT_RU_TASK、ACT_HI_PROCINST、ACT_HI_TASKINST、ACT_RE_PROCDEF这 5 张表是高频使用的,其他表(如ACT_RU_EVENT_SUBSCR、ACT_HI_DETAIL)除非特殊场景(如事件监听、变量明细),否则可以暂时忽略。
- 用 API 查询,而非手写 SQL
Activiti 的查询 API(如runtimeService.createProcessInstanceQuery()、taskService.createTaskQuery())已经封装了表关联逻辑,比手写 SQL 更安全、简单。例如:java// 通过业务主键查待办任务(一行代码,自动关联运行时表) List<Task> tasks = taskService.createTaskQuery() .processInstanceBusinessKey("EXP_001") // 业务主键 .list(); - 业务表中冗余 “流程实例 ID”,减少跨表查询
在业务表(如报销单表expense)中加一个字段proc_inst_id,流程发起时记录流程实例 ID。后续查询时,直接通过expense.proc_inst_id查流程信息,省去 “业务主键→流程实例 ID” 的中间步骤。
- 用工具辅助:可视化流程数据
- 开发环境用
Activiti Modeler(设计流程时预览表关联); - 生产环境用
Camunda Cockpit(Activiti 的商业版分支,可视化运行时数据、历史记录)。
- 开发环境用
五、案例:用 “简化思路” 处理一个实际场景
需求:查询 “报销单 ID=EXP_001” 的所有审批记录(包括待办和已完成)。
步骤:
- 从业务表
expense中拿到proc_inst_id(假设是PROC_001); - 查待办任务(运行时):java
List<Task> todoTasks = taskService.createTaskQuery() .processInstanceId("PROC_001") .list(); // 自动关联ACT_RU_TASK - 查已完成任务(历史):java
List<HistoricTaskInstance> doneTasks = historyService.createHistoricTaskInstanceQuery() .processInstanceId("PROC_001") .finished() // 只查已完成 .list(); // 自动关联ACT_HI_TASKINST
总结
Activiti 的表多是为了 “职责分离”,但只要抓住 “业务主键→流程实例 ID→任务 / 历史” 的核心链路,并用 API 而非手动操作,复杂度会大幅降低。初期可以先聚焦高频表和 API,遇到具体场景再针对性查文档,慢慢就会觉得 “表虽多,但逻辑清晰” 了。
如果有具体的查询 / 删除场景(比如 “如何批量删除过期流程”),可以再拿出来拆解,会更直观~

浙公网安备 33010602011771号