1. 流程生命周期与数据库表之间的逻辑关系
2. Flowable流程对象之间关系
3. act_ru_execution详解
ACTIVITI ACT_RU_EXECUTION 表
这个表是工作流程的核心表,流程的驱动都和合格表有密切的关系。
一般来讲一个流程实例都有一条主线。如果流程为直线流程,那么流程实例在这个表中只有一条记录对应。
ID_:EXECUTION主键,这个主键有可能和PROC_INST_ID_相同,相同的情况表示这条记录为主实例记录。
REV_:表示数据库表更新次数。
PROC_INST_ID_:一个流程实例不管有多少条分支实例,这个ID都是一致的。
比如以下流程:
这个对应的EXECUTION数据为:
这个图就描述的很清楚了。
10000001020315 记录为主流程,实例ID都为10000001020315,分支流程实例的父ID为10000001020315。
BUSINESS_KEY_:这个为业务主键,主流程才会使用业务主键,另外这个业务主键字段在表中有唯一约束。
PARENT_ID_:这个记录表示父实例ID,如上图,同步节点会产生两条执行记录,这两条记录的父ID为主线的ID。
PROC_DEF_ID_ :流程定义ID
SUPER_EXEC : 这个如果存在表示这个实例记录为一个外部子流程记录,对应主流程的主键ID。
ACT_ID_:表示流程运行到的节点,如上图主实例运行到ANDGateway1 节点。
两个子实例运行到UserTask1,UserTask2节点。
IS_ACTIVE_ : 是否活动流程实例,比如上图,主流程为非活动实例,下面两个为活动实例,如果UserTask2完成,那么这个值将变为0即非活动。
IS_CONCURRENT_:是否并发。上图同步节点后为并发,如果是并发多实例也是为1。
IS_SCOPE_: 这个字段我跟踪了一下不同的流程实例,如会签,子流程,同步等情况,发现主实例的情况这个字段为1,子实例这个字段为0。
TENANT_ID_ : 这个字段表示租户ID。可以应对多租户的设计。
IS_EVENT_SCOPE: 没有使用到事件的情况下,一般都为0。
SUSPENSION_STATE_: 这个表示是否暂停。
总结:
(1)如果是单例流程,执行对象ID就是流程实例ID
(2)如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同
(3)一个流程中,流程实例只有1个,执行对象可以存在多个。
4. Activiti业务键(businessKey)
问题:如何让业务对象和对应的流程 关联?
发现ProcessInstance 有个方法getBusinessKey()可以得到一个businessKey。
ProcessInstance 对应数据库中的表act_ru_execution有个字段BUSINESS_KEY_对应类中的businessKey,这个字段在创建表时自动被设置为unique
解决:
1、保证流程的ID和业务对象的类名一致。例如:流程id为LeaveBill,我们的业务对象的类名也创建为LeaveBill。
2、在流程启动的时候获取业务对象执行方法的时候传入businessKey,workflowService.startProcess(key,businessKey,vars);(这里vars为一些变量根据实际情况可有可无)businessKey 产生规则: className+“.”+objId
public void startProcess(Long id) {
//1. 获取业务对象
LeaveBill bill = this.get(id);
if(bill!=null){
// 修改业务对象状态
bill.setState(1);// 请假单状态 0初始录入,1.开始审批,2为审批通过
this.update(bill);
//2. 添加流程变量(Map)
Map<String,Object> vars = new HashMap<>();
vars.put("inputUser", bill.getUser().getName());
// 添加变量来描述业务对象的信息
String classType =bill.getClass().getSimpleName();
vars.put("classType", classType);
vars.put("objId", bill.getId());
//3. 启动流程
// 获取流程定义key
String key = classType;
// 获取业务键 产生规则: className+“.”+objId
String businessKey = classType +"." + bill.getId();
this.workflowService.startProcess(key,businessKey,vars);
}
}
3、根据以下方法就可以用taskId获取业务对象id
public String getBusinessObjId(String taskId) {
//1 获取任务对象
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
//2 通过任务对象获取流程实例
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
//3 通过流程实例获取“业务键”
String businessKey = pi.getBusinessKey();
//4 拆分业务键,拆分成“业务对象名称”和“业务对象ID”的数组
// a=b LeaveBill.1
String objId = null;
if(StringUtils.isNotBlank(businessKey)){
objId = businessKey.split("\\.")[1];
}
return objId;
}
4、根据业务键获取流程实例和任务
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey("LeaveBill.1").singleResult();
List<Task> task = taskService.createTaskQuery().processInstanceBusinessKey("LeaveBill.1").list();