zoukankan      html  css  js  c++  java
  • 【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
  • 相关阅读:
    Github简单使用
    软件架构
    软件架构
    软件架构
    VB.net 捕获项目全局异常
    C#里面的三种定时计时器:TIMER
    深入分析委托与事件
    C#预处理器指令
    C# 实现透明可移动窗体
    多元一次方程解法 C++
  • 原文地址:https://www.cnblogs.com/ios9/p/14142223.html
Copyright © 2011-2022 走看看