activiti5结束流程回退

1. 参考网上

参考1

activiti 手动回退一个结束的流程
参考2
activiti已结束子流程退回

2. 思路
ExecutionEntity 类实例化需要自己实现,按照ACT_RU_EXECUTION表结构,自定义实体类
act_hi_actinst 中有endEvent节点,需要删除这条记录,也需要自己实现
其他的对照表测试,调整数据
我这里是activiti5,activtiti6 差不多,把TaskRollBackService类中操作的类换成内置的,如 TaskEntityImpl, IdentityLinkEntityImpl,VariableInstanceEntityImpl,HistoricTaskInstanceEntityImpl,HistoricActivityInstanceEntityImpl ,对应TaskRollBackMapper.xml中类型也替换
3. 具体实现

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>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值