/**PageBeginHtml Block Begin **/ /***自定义返回顶部小火箭***/ /*生成博客目录的JS 开始*/ /*生成博客目录的JS 结束*/

【Activiti】activiti 手动回退一个结束的流程

【Activiti】activiti 手动回退一个结束的流程

1. 引言

最近有一个流程回退的任务,于是就上网搜,发现流程回退大都是针对没有结束的流程回退到上一步,而且给出的方法大都如吻末给出的相关链接中操作方式,试了试好像都不太好使。
于是就参照着网上的方法,顺带看接口看源码,试了试感觉总是不够灵活,还容易出错。
后来想了想,其实他流程所有的信息都存在了23张表中,每一步,无非就是改这些表信息,我抹清每一个审批动作他到底改变了那些表,我把这些表数据回滚不就好了。

2. 准备

  1. 首先我们需要先了解一下这23张表到底都是干什么的
  2. 我们要知道这些表是怎么变化的
    关于表变化,要把过程记录下来太麻烦了,我就不一一走了,给出一个参考链接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,可以参照源码中搬过来稍微改改就好了

相关链接:

  1. activiti执行过程,表变化
    https://blog.csdn.net/ccdust/article/details/52600804
  2. Activiti从当前任务任意回退至已审批任务
    https://www.bbsmax.com/A/obzb4o4B5E/
  3. Activiti6实现自由跳转
  4. https://segmentfault.com/a/1190000013952695
  5. Activiti6.0版本流程撤回、跳转、回退等操作
    https://blog.csdn.net/lianjie_c/article/details/79242009
posted @ 2020-12-16 09:32  一品堂.技术学习笔记  阅读(1876)  评论(0编辑  收藏  举报