Activiti工作流内建数据库表分析
如上图所示:activiti 5.22.0 版内建25张表,下面我将简要分析下这些表的作用。
1、表分类浅析
activiti的表主要分为以下几类:
1)通用数据表(2个)
act_ge_bytearray:二进制数据表,如流程定义、流程模板、流程图的字节流文件;
act_ge_property:属性数据表(不常用);
2)历史表(8个,HistoryService接口操作的表)
act_hi_actinst:历史节点表,存放流程实例运转的各个节点信息(包含开始、结束等非任务节点);
act_hi_attachment:历史附件表,存放历史节点上传的附件信息(不常用);
act_hi_comment:历史意见表,可改造用于保存节点审批意见、备注;
act_hi_detail:历史详情表,存储节点运转的一些信息(不常用);
act_hi_identitylink:历史流程人员表,存储流程各节点候选、办理人员信息,常用于查询某人或部门的已办任务;
act_hi_procinst:历史流程实例表,存储流程实例历史数据(包含正在运行的流程实例);
act_hi_taskinst:历史流程任务表,存储历史任务节点;
act_hi_varinst:流程历史变量表,存储流程历史节点的变量信息;
3)用户相关表(4个,IdentityService接口操作的表)
act_id_group:用户组信息表,对应节点选定候选组信息;
act_id_info:用户扩展信息表,存储用户扩展信息;
act_id_membership:用户与用户组关系表;
act_id_user:用户信息表,对应节点选定办理人或候选人信息;
4)流程定义、流程模板相关表(3个,RepositoryService接口操作的表)
act_re_deployment:部属信息表,存储流程定义、模板部署信息;
act_re_procdef:流程定义信息表,存储流程定义相关描述信息,但其真正内容存储在act_ge_bytearray表中,以字节形式存储;
act_re_model:流程模板信息表,存储流程模板相关描述信息,但其真正内容存储在act_ge_bytearray表中,以字节形式存储;
5)流程运行时表(6个,RuntimeService接口操作的表)
act_ru_task:运行时流程任务节点表,存储运行中流程的任务节点信息,重要,常用于查询人员或部门的待办任务时使用;
act_ru_event_subscr:监听信息表,不常用;
act_ru_execution:运行时流程执行实例表,记录运行中流程运行的各个分支信息(当没有子流程时,其数据与act_ru_task表数据是一一对应的);
act_ru_identitylink:运行时流程人员表,重要,常用于查询人员或部门的待办任务时使用;
act_ru_job:运行时定时任务数据表,存储流程的定时任务信息;
act_ru_variable:运行时流程变量数据表,存储运行中的流程各节点的变量信息;
6)其他(2个)
act_evt_log:事件日志表,不常用;
act_procdef_info:流程定义扩展表,不常用;
总结如下:
ACT_RE_: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU_: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_ID_: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
ACT_HI_: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。
2、流程定义与流程模板
activiti中的流程定义大致有以下2中方式生成:
1、由流程定义文件(即bpmn/xml文件,通常可通过eclipse的插件绘制生成)直接部署生成流程定义;
image.png
2、由模板文件转换部署而成;
详细编码请参考我的这篇文章:Activiti流程相关功能详解
需要注意的是,流程定义在部署时,是根据流程定义的key来区分是否是同一种流程,因此key相同的流程定义相继部署时,会生成该key对应的新版本的流程定义。
流程定义的key:zjjr-core-invite-chain:1:3597516
规则:流程的key:版本号:ID
而工作流中的流程模板也可由2种方式形成:
1、新建模板信息,然后利用activiti的模板设计工具(web页面)绘制后保存生成;
2、由流程定义文件(bpmn/xml)转换生成;
详情编码请参考我的这篇文章:Activiti模板相关功能详解
3、流程实例
啥叫流程实例?它与流程定义有何区别与联系呢?下面举个栗子:
流程定义好比我们的Java类,而流程实例就像由Java类生成的Java对象,因此,一个流程定义可以生成多个流程实例;而工作流的运转就是在流程实例的各个节点之间进行运转。
4、流程运转机制
1)启动流程
方法一:
ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey, Map<String, Object> var3);
方法二:
ProcessInstance submitStartFormData(String processDefinitionId, String businessKey, Map<String, String> properties)
一般用第一种,如果使用的是动态表单,选用第二种;
传入参数均为需要启动的流程定义ID、业务主键ID、启动参数;
【注】
1、启动参数通常包含办理的用户ID、网关条件值(可选),以及节点中自定义的变量值。
2、启动流程后,通常要往这几张表写入数据:act_ru_execution、act_ru_identitylink、act_ru_task、act_ru_variable、act_hi_actinst、act_hi_identitylink、act_hi_procinst、act_hi_taskinst、act_hi_varinst;
2)办理流程
Activiti在办理时默认有个认领任务的机制,比如某个任务节点同时配置了2个候选人办理,则其中一人认领后,另一个候选人则不能办理了;认领接口如下:
void claim(String taskId, String userId)
传入任务ID和用户ID即可认领(会校验该任务是否已被认领,如果已被认领,则去校验认领人和当前传入的用户是否一致,否则报错),源码如下:
protected Void execute(CommandContext commandContext, TaskEntity task) {
if (this.userId != null) {
if (task.getAssignee() != null) {
if (!task.getAssignee().equals(this.userId)) {
throw new ActivitiTaskAlreadyClaimedException(task.getId(), task.getAssignee());
}
} else {
task.setAssignee(this.userId, true, true);
}
} else {
task.setAssignee((String)null, true, true);
}
commandContext.getHistoryManager().recordTaskClaim(this.taskId);
return null;
}
当然也可以去掉认领这个步骤,即只要这个任务还没被其中一个候选人办理,那么无论哪个候选人都可以办理,但一旦被其中一人办理,这个任务就办理结束,流程自动流转到下一个节点;办理时代码如下:
// 办理流程
taskService.setAssignee(task.getId(), in.getUserId().toString());
taskService.complete(task.getId(), in.getVariables());
setAssignee作用是将办理该用流程的用户信息记录到act_ru_identitylink、act_hi_identitylink表中。
Activiti的运行表和历史表在流程运行时是同步记录数据的,当流程实例结束时,会删除运行表种的数据,保留历史表中的数据。
在有网关节点时,办理任务需要额外传入网关条件参数,指引工作流正确运转到下一个节点(网关条件对应具体的连接线):
如上图,在办理该节点时,需传入参数"wayType",值为1时流程运转至该连接线!
5、流程配置
1)节点办理人、候选人、候选组
可以将工作流对接至自定义的数据库用户、角色信息表,具体方法请参考我的这篇文章:Activiti对接业务表实现自定义用户和用户组
对接成功后可以改造流程设计器的选定用户、用户组界面,实现如下效果:
image.png
可以直接点击选择节点的办理人、候选人、候选组;
至此,我对工作流的一些常见知识做了初步总结,希望对读者有帮助!