【Activiti】activiti 手動回退一個結束的流程
1. 引言
最近有一個流程回退的任務,於是就上網搜,發現流程回退大都是針對沒有結束的流程回退到上一步,而且給出的方法大都如吻末給出的相關鏈接中操作方式,試了試好像都不太好使。
於是就參照着網上的方法,順帶看接口看源碼,試了試感覺總是不夠靈活,還容易出錯。
后來想了想,其實他流程所有的信息都存在了23張表中,每一步,無非就是改這些表信息,我抹清每一個審批動作他到底改變了那些表,我把這些表數據回滾不就好了。
2. 准備
- 首先我們需要先了解一下這23張表到底都是干什么的
- 我們要知道這些表是怎么變化的
關於表變化,要把過程記錄下來太麻煩了,我就不一一走了,給出一個參考鏈接https://blog.csdn.net/ccdust/article/details/52600804
ACT_EVT_LOG -- ACT_GE_* 通用數據, 用於不同場景下 ACT_GE_BYTEARRAY ACT_GE_PROPERTY -- ACT_HI_* history 歷史數據,每一步操作,都會在這些相關表記錄 ACT_HI_ACTINST ACT_HI_ATTACHMENT ACT_HI_COMMENT ACT_HI_DETAIL ACT_HI_IDENTITYLINK ACT_HI_PROCINST ACT_HI_TASKINST ACT_HI_VARINST --ACT_ID_* identity 身份信息 ACT_ID_GROUP ACT_ID_INFO ACT_ID_MEMBERSHIP ACT_ID_USER ACT_PROCDEF_INFO --ACT_RE_* repository 流程相關表(流程部署、流程模型、流程定義) ACT_RE_DEPLOYMENT ACT_RE_MODEL ACT_RE_PROCDEF --ACT_RU_* runtime 流程運行時表,流程結束,這些表數據清空 ACT_RU_EVENT_SUBSCR ACT_RU_EXECUTION ACT_RU_IDENTITYLINK ACT_RU_JOB ACT_RU_TASK ACT_RU_VARIABLE -- 可能我們業務結合,還會自定義一些表,保存重要信息
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
3. 回退
建議先找一個備份庫,直接用sql操作回退流程,找到每一步都的變化,直到成功,然后再在代碼中實現。
我這里記錄的是一個結束的流程回退,所以運行時表中已經沒有數據了,得從歷史表走起
3.1 先用sql試驗回退activiti表
-- 1. 查詢ACT_HI_TASKINST,返回歷史中task數據 select * from ACT_HI_TASKINST where ID_=#{taskId}; --2. 創建一個ACT_RU_EXECUTION記錄,每一個流程都有一個記錄,流程結束清除,但EXECUTION沒有歷史表,所以自己創建 # 參照插入 select * from ACT_RU_EXECUTION; insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_,IS_EVENT_SCOPE_, PARENT_ID_, SUPER_EXEC_, SUSPENSION_STATE_, CACHED_ENT_STATE_, TENANT_ID_, NAME_) values (...); -- 3. 將歷史數據task添加至ACT_RU_TASK # 參照插入 select * from ACT_RU_TASK; insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_) values (); -- 4. 恢復當前任務相關處理人到ACT_RUN_IDENTITYLINK select * from ACT_HI_IDENTITYLINK WHERE PROC_INST_ID_={} OR TASK_ID_={}; # 這里會返回一個list # 參照插入 select * from ACT_RU_IDENTITYLINK; insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (); -- 5. 添加運行時變量 ACT_RUN_VARIABLE select * from ACT_HI_VARINST where EXECUTION_ID_={}; # 這里會返回一個list # 參照插入 select * from ACT_RUN_VARIABLE; insert into ACT_RU_VARIABLE (ID_, REV_, TYPE_, NAME_, PROC_INST_ID_, EXECUTION_ID_, TASK_ID_, BYTEARRAY_ID_, DOUBLE_, LONG_ , TEXT_, TEXT2_) values (); -- 至此數據已經恢復到待辦中了,下一步還要回退已辦中的數據哈 -- 6. 撤銷已辦 # 因為這是回退一個已經結束的流程,所以那個流程肯定會在已辦列表里 # 看一下自己的已辦是根據什么查詢的對應修改相應數據 # 我這里是根據ACT_HI_TASKINST表endtime如果不為NULL,就到已辦中去了 # 所以我只需要將這條記錄中的endtime再改為NULL select * from ACT_HI_TASKINST where ID_={}; update ACT_HI_TASKINST set END_TIME_={} where ID_={};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
3.2 代碼實現回退activiti流程
代碼中實現,按上邊sql順序寫邏輯就好了
@Transactional public void rollbackTask(String taskId){ ProcessEngine pe = ActivitiConfiguration.getProcessEngine(); logger.info("begin to rollback task: [{}]",taskId); //1. select task HistoricTaskInstance hstTask = pe.getHistoryService().createHistoricTaskInstanceQuery() .taskId(taskId).singleResult(); if(hstTask == null){ throw new RuntimeException("task is not exists: "+ taskId); } //2. create a execution,SubExecutionEntity只是添加了一個構造器 ExecutionEntity execution = new SubExecutionEntity( hstTask.getExecutionId(), hstTask.getProcessInstanceId(), hstTask.getProcessDefinitionId(), hstTask.getTaskDefinitionKey()); logger.info("create a new run execution"); taskRollBackMapper.insertExecution(execution); //3. insert task into ACT_RU_TASK TaskEntity runTask = new TaskEntity(); runTask.setId(hstTask.getId()); runTask.setName(hstTask.getName()); runTask.setPriority(hstTask.getPriority()); runTask.setCreateTime(hstTask.getCreateTime()); runTask.setAssignee(hstTask.getAssignee()); runTask.setExecutionId(hstTask.getExecutionId()); runTask.setProcessInstanceId(hstTask.getProcessInstanceId()); runTask.setProcessDefinitionId(hstTask.getProcessDefinitionId()); runTask.setTaskDefinitionKey(hstTask.getTaskDefinitionKey()); logger.info("insert task[{}] into ACT_RU_TASK",taskId); taskRollBackMapper.insertTask(runTask); //4. insert task identitylink into ACT_RUN_IDENTITYLINK List<HistoricIdentityLinkEntity> hstIdentityLinks= taskRollBackMapper .selectHistoricIdentityLinksByProcessInstanceAndTaskId(hstTask.getProcessInstanceId(), hstTask.getId()); List<IdentityLinkEntity> identityLinkEntities = new ArrayList<>(); for (HistoricIdentityLinkEntity hstIdentityLink:hstIdentityLinks){ IdentityLinkEntity identityLink = new IdentityLinkEntity(); identityLink.setId(hstIdentityLink.getId()); identityLink.setType(hstIdentityLink.getType()); identityLink.setUserId(hstIdentityLink.getUserId()); identityLink.setTaskId(hstIdentityLink.getTaskId()); identityLink.setProcessInstanceId(hstIdentityLink.getProcessInstanceId()); identityLinkEntities.add(identityLink); } logger.info("bulk insert task identitylinks into ACT_RUN_IDENTITYLINK"); taskRollBackMapper.bulkInsertIdentityLink(identityLinkEntities); // 5. insert variables into ACT_RU_VARIABLE final List<HistoricVariableInstance> hstVariables = pe.getHistoryService().createHistoricVariableInstanceQuery() .executionId(hstTask.getExecutionId()).list(); List<VariableInstanceEntity> variables = new ArrayList<>(); for (HistoricVariableInstance hstVariable:hstVariables){ VariableInstanceEntity variableInstance = VariableInstanceEntity .create(hstVariable.getVariableName(), new StringType(100), hstVariable.getValue()); variableInstance.setId(hstVariable.getId()); variableInstance.setExecutionId(hstVariable.getProcessInstanceId()); variableInstance.setProcessInstanceId(hstVariable.getProcessInstanceId()); variableInstance.setTaskId(hstVariable.getTaskId()); variableInstance.setTextValue((String) hstVariable.getValue()); variables.add(variableInstance); } logger.info("bulk insert task variables into ACT_RU_VARIABLE"); taskRollBackMapper.bulkInsertVariableInstance(variables); // 6. remove task from history record HistoricTaskInstanceEntity hstTaskUpdate = new HistoricTaskInstanceEntity(); hstTaskUpdate.setId(hstTask.getId()); hstTaskUpdate.setProcessDefinitionId(hstTask.getProcessDefinitionId()); hstTaskUpdate.setTaskDefinitionKey(hstTask.getTaskDefinitionKey()); hstTaskUpdate.setProcessInstanceId(hstTask.getProcessInstanceId()); hstTaskUpdate.setExecutionId(hstTask.getExecutionId()); hstTaskUpdate.setName(hstTask.getName()); hstTaskUpdate.setAssignee(hstTask.getAssignee()); hstTaskUpdate.setStartTime(hstTask.getStartTime()); hstTaskUpdate.setClaimTime(hstTask.getClaimTime()); hstTaskUpdate.setEndTime(null); hstTaskUpdate.setDueDate(hstTask.getDueDate()); hstTaskUpdate.setDeleteReason(hstTask.getDeleteReason()); hstTaskUpdate.setPriority(hstTask.getPriority()); logger.info("remove task from history record"); taskRollBackMapper.updateHistoricTaskInstance(hstTaskUpdate); logger.info("rollback task: [{}] end",taskId); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
至於mapper.xml,可以參照源碼中搬過來稍微改改就好了
相關鏈接:
- activiti執行過程,表變化
https://blog.csdn.net/ccdust/article/details/52600804 - Activiti從當前任務任意回退至已審批任務
https://www.bbsmax.com/A/obzb4o4B5E/ - Activiti6實現自由跳轉
- https://segmentfault.com/a/1190000013952695
- Activiti6.0版本流程撤回、跳轉、回退等操作
https://blog.csdn.net/lianjie_c/article/details/79242009