赞
踩
参考1
activiti 手动回退一个结束的流程
参考2
activiti已结束子流程退回
ExecutionEntity 类实例化需要自己实现,按照ACT_RU_EXECUTION表结构,自定义实体类
act_hi_actinst 中有endEvent节点,需要删除这条记录,也需要自己实现
其他的对照表测试,调整数据
我这里是activiti5,activtiti6 差不多,把TaskRollBackService类中操作的类换成内置的,如 TaskEntityImpl, IdentityLinkEntityImpl,VariableInstanceEntityImpl,HistoricTaskInstanceEntityImpl,HistoricActivityInstanceEntityImpl ,对应TaskRollBackMapper.xml中类型也替换
TaskRollBackService类
package com.yl.activiti.service; import com.yl.activiti.bean.ExecutionInstEntity; import com.yl.activiti.mapper.TaskRollBackMapper; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.model.FlowElement; import org.activiti.engine.HistoryService; import org.activiti.engine.ProcessEngine; import org.activiti.engine.RepositoryService; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricIdentityLink; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.history.HistoricVariableInstance; import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity; import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.persistence.entity.VariableInstanceEntity; import org.activiti.engine.impl.variable.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; /** * 实现回退activiti5流程,结束的流程回退任务 * * @author liuxb * @date 2023/5/20 23:26 */ @Slf4j @Service public class TaskRollBackService { @Autowired private ProcessEngine processEngine; @Autowired private RepositoryService repositoryService; @Autowired private HistoryService historyService; @Autowired private TaskRollBackMapper taskRollBackMapper; /** * 结束的流程回退任务 * * @param taskId */ @Transactional(rollbackFor = Exception.class) public void rollback(String taskId) { log.info("begin to rollback task: [{}]", taskId); //1. 查询历史任务实例 HistoricTaskInstance hstTask = processEngine.getHistoryService() .createHistoricTaskInstanceQuery() .taskId(taskId) .singleResult(); if (hstTask == null) { throw new RuntimeException("任务[" + taskId + "] 不存在"); } //2. 创建 execution 这里采用自定义对象,activiti5内置对象实例化复杂,存在其他对象引用 FlowElement flowElement = repositoryService.getBpmnModel(hstTask.getProcessDefinitionId()) .getMainProcess() .getFlowElement(hstTask.getTaskDefinitionKey()); ExecutionInstEntity executionInstEntity = new ExecutionInstEntity(); executionInstEntity.setId(hstTask.getExecutionId()); executionInstEntity.setRevision(1); executionInstEntity.setProcessInstanceId(hstTask.getProcessInstanceId()); // 可能需要 executionInstEntity.setBusinessKey(null); executionInstEntity.setProcessDefinitionId(hstTask.getProcessDefinitionId()); executionInstEntity.setActivityId(hstTask.getTaskDefinitionKey()); executionInstEntity.setIsActive(true); executionInstEntity.setIsConcurrent(false); // 一般是主流程,如果回退的是有多个分支,含有子流程的,这里可能不是主流程 executionInstEntity.setIsScope(true); executionInstEntity.setParentId(null); executionInstEntity.setSuperExecutionId(null); executionInstEntity.setSuspensionState(1); executionInstEntity.setCachedEntityState(2); executionInstEntity.setTenantId(null); executionInstEntity.setName(null); log.info("创建一个新的 run execution"); taskRollBackMapper.insertExecution(executionInstEntity); //3.将历史数据task添加至ACT_RU_TASK TaskEntity runTask = new TaskEntity(); runTask.setId(hstTask.getId()); runTask.setExecutionId(hstTask.getExecutionId()); runTask.setProcessInstanceId(hstTask.getProcessInstanceId()); runTask.setProcessDefinitionId(hstTask.getProcessDefinitionId()); runTask.setName(hstTask.getName()); runTask.setTaskDefinitionKey(hstTask.getTaskDefinitionKey()); runTask.setAssignee(hstTask.getAssignee()); runTask.setPriority(hstTask.getPriority()); runTask.setCreateTime(hstTask.getCreateTime()); runTask.setSuspensionState(1); log.info("添加 task[{}] into ACT_RU_TASK", taskId); taskRollBackMapper.insertTask(runTask); //4. 恢复当前任务相关处理人到ACT_RUN_IDENTITYLINK List<HistoricIdentityLink> hstIdentityLinks = historyService.getHistoricIdentityLinksForProcessInstance(hstTask.getProcessInstanceId()); List<IdentityLinkEntity> identityLinkEntities = new ArrayList<>(); for (HistoricIdentityLink historicIdentityLink : hstIdentityLinks) { IdentityLinkEntity identityLink = new IdentityLinkEntity(); identityLink.setId(historicIdentityLink.getUserId()); identityLink.setType(historicIdentityLink.getType()); identityLink.setUserId(historicIdentityLink.getUserId()); identityLink.setTaskId(historicIdentityLink.getTaskId()); identityLink.setProcessInstanceId(historicIdentityLink.getProcessInstanceId()); identityLinkEntities.add(identityLink); } log.info("批量 insert task 相关处理人 into ACT_RUN_IDENTITYLINK"); taskRollBackMapper.bulkInsertIdentityLink(identityLinkEntities); // 5. 把变量从历史变量表中插入运行变量表中 // insert variables into ACT_RU_VARIABLE 运行时变量表和历史变量表id相同,流程流转时,自动把运行时变量表同步到历史变量表 final List<HistoricVariableInstance> hstVariables = processEngine.getHistoryService() .createHistoricVariableInstanceQuery() .processInstanceId(hstTask.getProcessInstanceId()) .executionId(hstTask.getExecutionId()) .list(); List<VariableInstanceEntity> variables = new ArrayList<>(); for (HistoricVariableInstance hstVariable : hstVariables) { VariableType type; if (hstVariable.getVariableTypeName().equals("boolean")) { type = new BooleanType(); } else if (hstVariable.getVariableTypeName().equals("integer")) { type = new IntegerType(); } else if (hstVariable.getVariableTypeName().equals("short")) { type = new ShortType(); } else if (hstVariable.getVariableTypeName().equals("long")) { type = new LongType(); } else if (hstVariable.getVariableTypeName().equals("double")) { type = new DoubleType(); } else { type = new StringType(100); } VariableInstanceEntity variableInstance = VariableInstanceEntity.create(hstVariable.getVariableName(), type, hstVariable.getValue()); variableInstance.setId(hstVariable.getId()); variableInstance.setTypeName(hstVariable.getVariableTypeName()); variableInstance.setName(hstVariable.getVariableName()); variableInstance.setExecutionId(hstVariable.getProcessInstanceId()); variableInstance.setProcessInstanceId(hstVariable.getProcessInstanceId()); variableInstance.setTaskId(hstVariable.getTaskId()); variableInstance.setValue(hstVariable.getValue()); variables.add(variableInstance); } log.info("批量 insert task variables into ACT_RU_VARIABLE"); taskRollBackMapper.bulkInsertVariableInstance(variables); // 至此数据已经恢复到待办中了,下一步还要回退已办中的数据 // 6. 历史任务结束时间、用时、删除原因 修改为null HistoricTaskInstanceEntity hstTaskUpdate = new HistoricTaskInstanceEntity(); hstTaskUpdate.setId(hstTask.getId()); hstTaskUpdate.setProcessDefinitionId(hstTask.getProcessDefinitionId()); hstTaskUpdate.setExecutionId(hstTask.getExecutionId()); hstTaskUpdate.setName(hstTask.getName()); hstTaskUpdate.setProcessInstanceId(hstTask.getProcessInstanceId()); hstTaskUpdate.setOwner(hstTask.getOwner()); hstTaskUpdate.setAssignee(hstTask.getAssignee()); hstTaskUpdate.setClaimTime(hstTask.getClaimTime()); hstTaskUpdate.setEndTime(null); hstTaskUpdate.setDurationInMillis(null); hstTaskUpdate.setDeleteReason(null); hstTaskUpdate.setTaskDefinitionKey(hstTask.getTaskDefinitionKey()); hstTaskUpdate.setPriority(hstTask.getPriority()); hstTaskUpdate.setDueDate(hstTask.getDueDate()); hstTaskUpdate.setCategory(hstTask.getCategory()); log.info("history task 结束时间设置为null"); taskRollBackMapper.updateHistoricTaskInstance(hstTaskUpdate); // 7. 删除历史节点表 节点类型是endEvent的 记录 List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(hstTask.getProcessInstanceId()) .executionId(hstTask.getExecutionId()) .activityType("endEvent") .list(); log.info("删除 act_hi_actinst 中 endEvent节点"); taskRollBackMapper.deleteHisActInst(historicActivityInstanceList.get(0)); // 8. 修改业务表,修改业务相关的逻辑 // ... log.info("rollback task: [{}] end", taskId); } }
TaskRollBackMapper
package com.yl.activiti.mapper; import com.yl.activiti.bean.ExecutionInstEntity; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity; import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.persistence.entity.VariableInstanceEntity; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 实现回退activiti流程,结束的流程回退任务 对activiti5的表操作 * 参考 activiti-engine-5.23.0.jar org.activiti.db.mapping.entity 下XX.xml * * @author liuxb * @date 2023/5/21 14:33 */ @Mapper public interface TaskRollBackMapper { /** * 添加到ACT_RU_EXECUTION * * @param executionInstEntity * @return */ int insertExecution(ExecutionInstEntity executionInstEntity); /** * 添加到ACT_RU_TASK * * @param taskEntity * @return */ int insertTask(TaskEntity taskEntity); /** * 批量添加ACT_RU_IDENTITYLINK * * @param identityLinkEntities * @return */ int bulkInsertIdentityLink(@Param("list") List<IdentityLinkEntity> identityLinkEntities); /** * 批量插入到ACT_RU_VARIABLE * * @param variables * @return */ int bulkInsertVariableInstance(@Param("list") List<VariableInstanceEntity> variables); /** * 修改历史任务 * * @param historicTaskInstanceEntity * @return */ int updateHistoricTaskInstance(HistoricTaskInstanceEntity historicTaskInstanceEntity); /** * 删除历史活动实例 * * @param historicActivityInstance * @return */ int deleteHisActInst(HistoricActivityInstance historicActivityInstance); }
ExecutionInstEntity 类
package com.yl.activiti.bean; import lombok.Data; /** * 运行时流程实例 * <p> activiti5内置的ExecutionEntity属性存在引用对象,不容易创建,这里自定义 * * @author liuxb * @date 2023/5/21 16:10 */ @Data public class ExecutionInstEntity { /** * id,executionId */ private String id; /** * 版本号,默认1 */ private Integer revision; /** * 流程实例ID */ private String processInstanceId; /** * 业务表主键 业务key */ private String businessKey; /** * 流程定义ID */ private String processDefinitionId; /** * 当前流程所在的节点ID */ private String activityId; /** * 是否处于激活状态(0否,1是) 一般为1 */ private Boolean isActive; /** * 是否处于并发状态(0否,1是) 一般为0 */ private Boolean isConcurrent; /** * 是否是主流程实例(0否,1是)一般为1 */ private Boolean isScope; /** * 是否是事件(0否,1是) 一般为0 */ private Boolean isEventScope; /** * 父id */ private String parentId; /** * 父运行时流程实例id */ private String superExecutionId; /** * 挂起状态(1正常,2挂起) */ private Integer suspensionState; /** * 流程实体的缓冲,取值为0~7,无法确定 可设置为2 */ private Integer cachedEntityState; /** * 租户id */ private Integer tenantId; /** * 名称 */ private String name; }
TaskRollBackMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace='com.yl.activiti.mapper.TaskRollBackMapper'> <insert id="insertExecution" parameterType="com.yl.activiti.bean.ExecutionInstEntity"> 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 ( #{id ,jdbcType=VARCHAR}, 1, #{processInstanceId, jdbcType=VARCHAR}, #{businessKey, jdbcType=VARCHAR}, #{processDefinitionId ,jdbcType=VARCHAR}, #{activityId ,jdbcType=VARCHAR}, #{isActive ,jdbcType=BOOLEAN}, #{isConcurrent ,jdbcType=BOOLEAN}, #{isScope ,jdbcType=BOOLEAN}, #{isEventScope ,jdbcType=BOOLEAN}, #{parentId, jdbcType=VARCHAR}, #{superExecutionId, jdbcType=VARCHAR}, #{suspensionState, jdbcType=INTEGER}, #{cachedEntityState, jdbcType=INTEGER}, #{tenantId, jdbcType=VARCHAR}, #{name, jdbcType=VARCHAR} ) </insert> <insert id="insertTask" parameterType="org.activiti.engine.impl.persistence.entity.TaskEntity"> 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 (#{id, jdbcType=VARCHAR}, 1, #{name, jdbcType=VARCHAR}, #{parentTaskId, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{priority, jdbcType=INTEGER}, #{createTime, jdbcType=TIMESTAMP}, #{owner, jdbcType=VARCHAR}, #{assignee, jdbcType=VARCHAR}, #{delegationStateString, jdbcType=VARCHAR}, #{executionId, jdbcType=VARCHAR}, #{processInstanceId, jdbcType=VARCHAR}, #{processDefinitionId, jdbcType=VARCHAR}, #{taskDefinitionKey, jdbcType=VARCHAR}, #{dueDate, jdbcType=TIMESTAMP}, #{category, jdbcType=VARCHAR}, #{suspensionState, jdbcType=INTEGER}, #{tenantId, jdbcType=VARCHAR}, #{formKey, jdbcType=VARCHAR} ) </insert> <insert id="bulkInsertIdentityLink" parameterType="org.activiti.engine.impl.persistence.entity.IdentityLinkEntity"> insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values <foreach collection="list" item="identityLink" index="index" separator=","> (#{identityLink.id, jdbcType=VARCHAR}, 1, #{identityLink.type, jdbcType=VARCHAR}, #{identityLink.userId, jdbcType=VARCHAR}, #{identityLink.groupId, jdbcType=VARCHAR}, #{identityLink.taskId, jdbcType=VARCHAR}, #{identityLink.processInstanceId, jdbcType=VARCHAR}, #{identityLink.processDefId, jdbcType=VARCHAR}) </foreach> </insert> <insert id="bulkInsertVariableInstance" parameterType="java.util.List"> INSERT INTO ACT_RU_VARIABLE (ID_, REV_, TYPE_, NAME_, PROC_INST_ID_, EXECUTION_ID_, TASK_ID_, BYTEARRAY_ID_, DOUBLE_, LONG_ , TEXT_, TEXT2_) VALUES <foreach collection="list" item="variable" index="index" separator=","> (#{variable.id, jdbcType=VARCHAR}, 1, #{variable.typeName, jdbcType=VARCHAR }, #{variable.name, jdbcType=VARCHAR}, #{variable.processInstanceId, jdbcType=VARCHAR}, #{variable.executionId, jdbcType=VARCHAR}, #{variable.taskId, jdbcType=VARCHAR}, #{variable.byteArrayRef, typeHandler=org.activiti.engine.impl.persistence.ByteArrayRefTypeHandler}, #{variable.doubleValue, jdbcType=DOUBLE}, #{variable.longValue, jdbcType=BIGINT}, #{variable.textValue, jdbcType=VARCHAR}, #{variable.textValue2, jdbcType=VARCHAR}) </foreach> </insert> <update id="updateHistoricTaskInstance" parameterType="org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity"> update ACT_HI_TASKINST set PROC_DEF_ID_ = #{processDefinitionId, jdbcType=VARCHAR}, EXECUTION_ID_ = #{executionId, jdbcType=VARCHAR}, NAME_ = #{name, jdbcType=VARCHAR}, PARENT_TASK_ID_ = #{parentTaskId, jdbcType=VARCHAR}, DESCRIPTION_ = #{description, jdbcType=VARCHAR}, OWNER_ = #{owner, jdbcType=VARCHAR}, ASSIGNEE_ = #{assignee, jdbcType=VARCHAR}, CLAIM_TIME_ = #{claimTime, jdbcType=TIMESTAMP}, END_TIME_ = #{endTime, jdbcType=TIMESTAMP}, DURATION_ = #{durationInMillis ,jdbcType=BIGINT}, DELETE_REASON_ = #{deleteReason ,jdbcType=VARCHAR}, TASK_DEF_KEY_ = #{taskDefinitionKey ,jdbcType=VARCHAR}, FORM_KEY_ = #{formKey ,jdbcType=VARCHAR}, PRIORITY_ = #{priority, jdbcType=INTEGER}, DUE_DATE_ = #{dueDate, jdbcType=TIMESTAMP}, CATEGORY_ = #{category, jdbcType=VARCHAR} where ID_ = #{id} </update> <delete id="deleteHisActInst"> delete from ACT_HI_ACTINST where PROC_INST_ID_ = #{processInstanceId} and EXECUTION_ID_= #{executionId} and ACT_TYPE_ = #{activityType} </delete> </mapper>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。