camunda框架学习(十六)中国式流程系列_getbpmnmodelinstance-程序员宅基地

技术标签: 流程引擎  java  知识图谱  eclipse  

一、流程实例批量查询

在这里插入图片描述

    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_1jtymod</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_1jtymod" sourceRef="StartEvent_1" targetRef="Activity_08hk2ft" />
    <bpmn:userTask id="Activity_1nicj02" name="【总经理】审批">
      <bpmn:incoming>Flow_11hhq0u</bpmn:incoming>
      <bpmn:outgoing>Flow_1ajzlub</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:userTask id="Activity_08hk2ft" name="请假申请">
      <bpmn:incoming>Flow_1jtymod</bpmn:incoming>
      <bpmn:outgoing>Flow_11hhq0u</bpmn:outgoing>
    </bpmn:userTask>
    @Test
    public void startProcessInstanceByKey() {
    
        for (int i = 0; i < 10; i++) {
    
            runtimeService.startProcessInstanceByKey("batch");
        }
    }
    /**
     * select distinct RES.*
     * FROM ACT_RU_EXECUTION RES
     * INNER JOIN ACT_RE_PROCDEF P
     * ON RES.PROC_DEF_ID_ = P.ID_
     * WHERE RES.PARENT_ID_ is null and ( RES.PROC_INST_ID_ IN ( '11317' , '11321' ) ) order by RES.ID_ asc
     * LIMIT 2147483647 OFFSET 0;
     */
    @Test
    public void createProcessInstanceQuery() {
    
        Set<String> processInstanceIds = new HashSet<>();
        processInstanceIds.add("11321");
        processInstanceIds.add("11317");

        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
                .processInstanceIds(processInstanceIds)
                .list();
        System.out.println(list);
    }

二、流程实例同步方式批量迁移

在这里插入图片描述

    <bpmn:userTask id="Activity_01oj8gn" name="新节点">
      <bpmn:incoming>Flow_1ajzlub</bpmn:incoming>
      <bpmn:outgoing>Flow_14eyxev</bpmn:outgoing>
    </bpmn:userTask>

目前一些流程已经运行到了【请假申请】,一些运行到了【总经理审批】,这时候部署了第二个版本,新增了一个节点【新节点】,这时候要让以前的实例(尚未运行完)走到最新的,该怎么实现呢?

原实例表:
在这里插入图片描述
1、迁移节点


    @Test
    public void newMigration() {
    
        String sourceProcessDefinitionId = "batch:1:3";
        String targetProcessDefinitionId = "batch:2:303";

        String sourceActivityId = "Activity_08hk2ft";
        String targetActivityId = "Activity_01oj8gn";

        MigrationPlan migrationPlan = runtimeService.createMigrationPlan(sourceProcessDefinitionId, targetProcessDefinitionId)
                .mapActivities(sourceActivityId, targetActivityId)
                .build();

        runtimeService.newMigration(migrationPlan)
                .processInstanceIds("101", "105")
                .execute();

    }

实例表改了:
在这里插入图片描述
任务表也改了:
在这里插入图片描述

这时候完成104108,对应的流程实例就运行结束了。

注意:名称并没有更改,也无法直接迁移到连线。只能迁移到节点。

三、流程实例异步方式批量迁移

    @Test
    public void newMigration() {
    
        String sourceProcessDefinitionId = "batch:1:3";
        String targetProcessDefinitionId = "batch:2:303";

        String sourceActivityId = "Activity_08hk2ft";
        String targetActivityId = "Activity_01oj8gn";

        MigrationPlan migrationPlan = runtimeService.createMigrationPlan(sourceProcessDefinitionId, targetProcessDefinitionId)
                .mapActivities(sourceActivityId, targetActivityId)
                .build();

        runtimeService.newMigration(migrationPlan)
                .processInstanceIds("125", "129")
                .executeAsync();

    }

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
批次查询:

    @Test
    public void createBatchQuery() {
    
        List<Batch> list = managementService.createBatchQuery()
                .list();
        for (Batch batch : list) {
    
            System.out.println("#########");
            System.out.println(batch.getId());
            System.out.println(batch.getType());
            System.out.println(batch.getTotalJobs());
            System.out.println("#########");
        }

    }

激活批次执行:

    /**
     * update ACT_RU_JOB set REV_ = REV_ + 1, SUSPENSION_STATE_ = 1 WHERE JOB_DEF_ID_ = '503';
     * ------------------------------------------------------------------------------------------------------------------------
     * update ACT_RU_JOBDEF set REV_ = REV_ + 1, SUSPENSION_STATE_ = 1 WHERE ID_ = '504';
     * ------------------------------------------------------------------------------------------------------------------------
     * update ACT_RU_JOB set REV_ = REV_ + 1, SUSPENSION_STATE_ = 1 WHERE JOB_DEF_ID_ = '503';
     * ------------------------------------------------------------------------------------------------------------------------
     * update ACT_RU_JOBDEF set REV_ = REV_ + 1, SUSPENSION_STATE_ = 1 WHERE ID_ = '504';
     * ------------------------------------------------------------------------------------------------------------------------
     */
    @Test
    public void activateBatchById() {
    
        String batchId = "502";
        managementService.activateBatchById(batchId);
    }

camunda框架有bug,这里没有成功执行。

我们可以手动执行ACT_RU_JOB,执行后ACT_RU_JOB会产生3个任务,将其完成即可。先完成``instance-migration,最后完成batch-monitor-job`,监听到迁移完了,会删除批次。

    @Test
    public void executeJob() {
    
        String jobId = "605";
        managementService.executeJob(jobId);
    }

删除批次:

采用异步删除,如果发现迁移有误,则可以删除批次

    /**
     * ------------------------------------------------------------------------------------------------------------------------
     * delete FROM ACT_RU_JOB WHERE ID_ = '706' and REV_ = 1;
     * ------------------------------------------------------------------------------------------------------------------------
     * delete FROM ACT_GE_BYTEARRAY WHERE ID_ = '701' and REV_ = 1;
     * ------------------------------------------------------------------------------------------------------------------------
     * delete B FROM ACT_GE_BYTEARRAY B INNER JOIN ACT_HI_JOB_LOG J ON B.ID_ = J.JOB_EXCEPTION_STACK_ID_ and J.JOB_EXCEPTION_STACK_ID_ is not null and J.JOB_DEF_ID_ = '704';
     * ------------------------------------------------------------------------------------------------------------------------
     * delete FROM ACT_HI_JOB_LOG WHERE JOB_DEF_ID_ = '703';
     * ------------------------------------------------------------------------------------------------------------------------
     * DELETE FROM ACT_RU_JOBDEF WHERE ID_ = '703' and REV_ = 1;
     */
    @Test
    public void deleteBatch() {
    
        String batchId = "702";
        boolean cascade = true;
        managementService.deleteBatch(batchId, cascade);
    }

四、模板拷贝

  @Test
    public void getBpmnModelInstance() {
    
        String processDefinitionId = "batch:2:303";
        BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processDefinitionId);
        BpmnModelInstance clone = bpmnModelInstance.clone();

        ModelElementInstance modelElement = clone.getModelElementById("Activity_01oj8gn");

        UserTask userTask = (UserTask) modelElement;
        userTask.setName("新节点复制");
        userTask.setId("utask_333");

        repositoryService.createDeployment().addModelInstance("复制.bpmn", clone).deploy();
    }

在这里插入图片描述

 identityService.setAuthenticatedUserId("peng111");

在这里插入图片描述

  @Test
    public void newMigrationLog() {
    
        identityService.setAuthenticatedUserId("peng111");

        String sourceProcessDefinitionId = "batch:2:303";
        String targetProcessDefinitionId = "batch:3:1803";
        MigrationPlan migrationPlan = runtimeService.createMigrationPlan(sourceProcessDefinitionId, targetProcessDefinitionId)
                .mapActivities("Activity_08hk2ft", "Activity_01oj8gn")
                .build();
        runtimeService.newMigration(migrationPlan)
                .processInstanceIds("137")
                .execute();
    }

另外,历史记录要调到最高

<property name="historyLevel" value="HISTORY_LEVEL_FULL"/>
    @Test
    public void createUserOperationLogQuery() {
    
        List<UserOperationLogEntry> list = historyService.createUserOperationLogQuery().list();
        System.out.println(list);
    }

六、流程实例任意跳转节点

在这里插入图片描述

    @Test
    public void createModification() {
    
        String processDefinitionId = "batch:2:303";

        runtimeService.createModification(processDefinitionId)
                .startAfterActivity("Activity_1nicj02")
//                .startBeforeActivity()
//                .startTransition()//跳转到连线,可以触发监听器
                .processInstanceIds("121")
                .cancelAllForActivity("Activity_08hk2ft", true)//原有的实例节点ID,是否取消原有实例
                .execute();
    }

七、实例批量挂起与激活

在这里插入图片描述

    @Test
    public void updateProcessInstanceSuspensionState() {
    
        //记录日志
        identityService.setAuthenticatedUserId("peng111");

        runtimeService.updateProcessInstanceSuspensionState()
                .byProcessInstanceIds(Arrays.asList("121"))
                .suspendAsync();
    }
    @Test
    public void executeJob() {
    
        String jobId = "2304";
        managementService.executeJob(jobId);
    }
    @Test
    public void updateProcessInstanceSuspensionState() {
    
        identityService.setAuthenticatedUserId("peng111");

        runtimeService.updateProcessInstanceSuspensionState()
                .byProcessInstanceIds(Arrays.asList("121"))
                .activateAsync();

    }

八、重新复活死亡的流程实例

在这里插入图片描述

    @Test
    public void restartProcessInstances() {
    
       //操作人日志记录
       identityService.setAuthenticatedUserId("peng111");

        String processDefinitionId = "batch:3:1803";
        runtimeService.restartProcessInstances(processDefinitionId)
                .startTransition("Flow_11hhq0u")//从连线开始
                .processInstanceIds("137")
                .execute();
    }

本质相当于是新发起了一个流程。

九、批量删除流程实例

在这里插入图片描述

    @Test
    public void deleteProcessInstances() {
    
        List<String> processInstanceIds = new ArrayList<>();
        processInstanceIds.add("2002");
        processInstanceIds.add("2101");
        runtimeService.deleteProcessInstances(processInstanceIds, "测试删除原因", true, true);
        //runtimeService.deleteProcessInstancesAsync(processInstanceIds, runtimeService.createProcessInstanceQuery(), "测试删除原因", true, true);
    }


    @Test
    public void deleteProcessInstancesAsync() {
    
        List<String> processInstanceIds = new ArrayList<>();
        processInstanceIds.add("2002");
        processInstanceIds.add("2101");
        runtimeService.deleteProcessInstancesAsync(processInstanceIds, runtimeService.createProcessInstanceQuery(), "测试删除原因", true, true);
    }

异步的还需要完成job的手工完成

十、历史数据迁移

参考:https://blog.csdn.net/VeastLee/article/details/109546895

十一、会签、加签、任务转让与委派

参考:会签、加签、任务转让与委派l

会签:
在这里插入图片描述

nrOfInstances实例的数目
nrOfCompletedInstances 完成实例的数目
nrOfActiveInstance 未完成实例的数目
loopCounter 循环计数器,办理人在列表中的索引。

  • loop cardinality:循环基数。可选项。可以直接填整数,表示会签的人数。
  • Collection:集合。可选项。会签人数的集合,通常为list。和loop cardinality二选一
  • Element variable:元素变量。选择Collection时必选,为collection集合每次遍历的元素
  • Completion condition:完成条件。可选。Activiti会签有个特性,比如设置一个人完成后会签结束,那么其他人的代办任务都会消失。

条件${nrOfInstances == nrOfCompletedInstances}表示所有人员审批完成后会签结束。
条件${ nrOfCompletedInstances == 1}表示一个人完成审批,该会签就结束。

十二、驳回到起始节点

@Test
public void reject() {
    
   String processInstanceId="";
   String message="项目的金额款项结算不正确";
   Task task = taskService.createTaskQuery()
         .taskAssignee("admin") //当前登录用户的id
         .processInstanceId(processInstanceId)
         .singleResult();
   ActivityInstance tree = runtimeService.getActivityInstance(processInstanceId);
   List<HistoricActivityInstance> resultList = historyService
         .createHistoricActivityInstanceQuery()
         .processInstanceId(processInstanceId)
         .activityType("userTask")
         .finished()
         .orderByHistoricActivityInstanceEndTime()
         .asc()
         .list();
   //得到第一个任务节点的id
   HistoricActivityInstance historicActivityInstance = resultList.get(0);
   String toActId = historicActivityInstance.getActivityId();
   String assignee = historicActivityInstance.getAssignee();
   //设置流程中的可变参数
   Map<String, Object> taskVariable = new HashMap<>(2);
   taskVariable.put("user", assignee);
   taskVariable.put("formName", "项目建设");
   taskService.createComment(task.getId(), processInstanceId, "驳回原因:" + message);
   runtimeService.createProcessInstanceModification(processInstanceId)
         .cancelActivityInstance(getInstanceIdForActivity(tree, task.getTaskDefinitionKey()))//关闭相关任务
         .setAnnotation("进行了驳回到第一个任务节点操作")
         .startBeforeActivity(toActId)//启动目标活动节点
         .setVariables(taskVariable)//流程的可变参数赋值
         .execute();
}
private String getInstanceIdForActivity(ActivityInstance activityInstance, String activityId) {
    
   ActivityInstance instance = getChildInstanceForActivity(activityInstance, activityId);
   if (instance != null) {
    
      return instance.getId();
   }
   return null;
}

private ActivityInstance getChildInstanceForActivity(ActivityInstance activityInstance, String activityId) {
    
   if (activityId.equals(activityInstance.getActivityId())) {
    
      return activityInstance;
   }
   for (ActivityInstance childInstance : activityInstance.getChildActivityInstances()) {
    
      ActivityInstance instance = getChildInstanceForActivity(childInstance, activityId);
      if (instance != null) {
    
         return instance;
      }
   }
   return null
}

写法2:撤回

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    HistoryService historyService = processEngine.getHistoryService();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    //获取当前任务,未办理任务id
    HistoricTaskInstance currTask = historyService.createHistoricTaskInstanceQuery()
            .taskId(taskId)
            .singleResult();
    //获取流程实例
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
            .processInstanceId(currTask.getProcessInstanceId())
            .singleResult();
    //获取流程定义
    ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
            .getDeployedProcessDefinition(currTask.getProcessDefinitionId());

    ActivityImpl currActivity = (processDefinitionEntity)
            .findActivity(currTask.getTaskDefinitionKey());
    //清除当前活动出口
    List<PvmTransition> originPvmTransitionList = new ArrayList<PvmTransition>();
    List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
    for (PvmTransition pvmTransition : pvmTransitionList) {
    
        originPvmTransitionList.add(pvmTransition);
    }
    pvmTransitionList.clear();
    //查找上一个user task节点
    List<HistoricActivityInstance> historicActivityInstances = historyService
            .createHistoricActivityInstanceQuery().activityType("userTask")
            .processInstanceId(processInstance.getId())
            .finished()
            .orderByHistoricActivityInstanceEndTime().asc().list();
    TransitionImpl transitionImpl = null;
    if (historicActivityInstances.size() > 0) {
    
        ActivityImpl lastActivity = (processDefinitionEntity)
                .findActivity(historicActivityInstances.get(0).getActivityId());
        //创建当前任务的新出口
        transitionImpl = currActivity.createOutgoingTransition(lastActivity.getId());
        transitionImpl.setDestination(lastActivity);
    }
    // 完成任务
    List<Task> tasks = taskService.createTaskQuery()
            .processInstanceId(processInstance.getId())
            .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
    for (Task task : tasks) {
    
        taskService.complete(task.getId());
        historyService.deleteHistoricTaskInstance(task.getId());
    }
    // 恢复方向
    currActivity.getOutgoingTransitions().remove(transitionImpl);
    for (PvmTransition pvmTransition : originPvmTransitionList) {
    
        pvmTransitionList.add(pvmTransition);
    }

	/**
	 * 撤回流程
	 */
	private void recall() {
    
		List<String> roleCodeList = new ArrayList<>();
		roleCodeList.add("user1");
		// 取得已提交的任务
		HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
				.taskCandidateGroupIn(roleCodeList).singleResult();
		// HistoricTaskInstance historicTaskInstance =
		// historyService.createHistoricTaskInstanceQuery().taskAssignee(assignee).singleResult();
		// HistoricTaskInstance historicTaskInstance =
		// historyService.createHistoricTaskInstanceQuery().taskCandidateUser(assignee).singleResult();
		System.out.println(historicTaskInstance.getId());
		// 取得流程实例
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();
		System.out.println(processInstance.getId());
		Map<String, Object> variables = runtimeService.getVariables(historicTaskInstance.getExecutionId());
		System.out.println(variables);
		// 取得流程定义
		ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService
				.getProcessDefinition(historicTaskInstance.getProcessDefinitionId());
		System.out.println(definitionEntity);
		// 取得上一步活动
		ActivityImpl hisActivity = definitionEntity.findActivity(historicTaskInstance.getTaskDefinitionKey());
		System.out.println(hisActivity);
		// 取得当前活动
		List<PvmTransition> currTransitionList = hisActivity.getOutgoingTransitions();
		System.out.println(currTransitionList);

		for (PvmTransition currTransition : currTransitionList) {
    
			PvmActivity currActivity = currTransition.getDestination();
			List<Task> currTasks = taskService.createTaskQuery().processInstanceId(processInstance.getId())
					.taskDefinitionKey(currActivity.getId()).list();
			for (Task currTask : currTasks) {
    
				ArrayList<PvmTransition> oriPvmTransitionList = new ArrayList<>();
				List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
				System.out.println(pvmTransitionList);
				for (PvmTransition pvmTransition : pvmTransitionList) {
    
					oriPvmTransitionList.add(pvmTransition);
				}
				System.out.println(oriPvmTransitionList);
				pvmTransitionList.clear();
				// 建立新方向
				ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definitionEntity)
						.findActivity(currActivity.getId());
				TransitionImpl newTransition = nextActivityImpl.createOutgoingTransition();
				newTransition.setDestination(hisActivity);
				taskService.claim(currTask.getId(), null);
				taskService.complete(currTask.getId(), variables);
				historyService.deleteHistoricTaskInstance(currTask.getId());

				// 恢复方向
				hisActivity.getIncomingTransitions().remove(newTransition);
				List<PvmTransition> pvmTList = currActivity.getOutgoingTransitions();
				pvmTList.clear();
				for (PvmTransition pvmTransition : oriPvmTransitionList) {
    
					pvmTransitionList.add(pvmTransition);
				}
				System.out.println(pvmTransitionList);
			}
		}
		historyService.deleteHistoricTaskInstance(historicTaskInstance.getId());
	}


camunda获流程的审批记录详情示例

//所有的审批意见都会存到 ACT_HI_COMMENT 的表中,因此需要如下接口获取
List<Comment> taskComments = taskService.getTaskComments(taskId);
//完整示例 
@Test
public void taskGetComment(){
    
   List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
         .processInstanceId("d66d9908-9a71-11ea-9906-40e230303674")
         .orderByHistoricActivityInstanceStartTime()
         .asc()
         .list();
   List<Map<String,Object>> result=new ArrayList<>(list.size());
   System.out.println(list.size());
   for (HistoricActivityInstance historicActivityInstance : list) {
    
      Map<String,Object> map=new HashMap<>(5);
      String taskId = historicActivityInstance.getTaskId();
      List<Comment> taskComments = taskService.getTaskComments(taskId);
      System.out.println(taskComments.size());
      map.put("activityName",historicActivityInstance.getActivityName());
      map.put("activityType",matching(historicActivityInstance.getActivityType()));
      map.put("assignee",historicActivityInstance.getAssignee()==null?"无":historicActivityInstance.getAssignee());
      map.put("startTime",DateFormatUtils.format(historicActivityInstance.getStartTime(),"yyyy-MM-dd HH:mm:ss") );
      map.put("endTime",DateFormatUtils.format(historicActivityInstance.getEndTime(),"yyyy-MM-dd HH:mm:ss"));
      map.put("costTime",getDatePoor(historicActivityInstance.getEndTime(),historicActivityInstance.getStartTime()));

      if (taskComments.size()>0){
    
         map.put("message",taskComments.get(0).getFullMessage());
      }else {
    
         map.put("message","无");
      }
      result.add(map);
   }
   System.out.println(JSON.toJSONString(result));
}

private String matching(String ActivityType){
    
   String value="";
   switch (ActivityType){
    
      case "startEvent":
         value="流程开始";
         break;
      case "userTask":
         value="用户处理";
         break;
      case "noneEndEvent":
         value="流程结束";
         break;
      default:
         value="未知节点";
         break;
   }
   return value;
}

public  String getDatePoor(Date endDate, Date nowDate) {
    

   long nd = 1000 * 24 * 60 * 60;
   long nh = 1000 * 60 * 60;
   long nm = 1000 * 60;
   long ns = 1000;
   // 获得两个时间的毫秒时间差异
   long diff = endDate.getTime() - nowDate.getTime();
   // 计算差多少天
   long day = diff / nd;
   // 计算差多少小时
   long hour = diff % nd / nh;
   // 计算差多少分钟
   long min = diff % nd % nh / nm;
   // 计算差多少秒//输出结果
   long sec = diff % nd % nh % nm / ns;
   return day + "天" + hour + "小时" + min + "分钟"+ sec + "秒";
}

 //结果展示
[{
    
    "costTime": "0天0小时0分钟0秒",
    "activityName": "开始",
    "startTime": "2020-05-20 16:13:50",
    "assignee": "无",
    "endTime": "2020-05-20 16:13:50",
    "activityType": "流程开始",
    "message": "无"
}, {
    
    "costTime": "0天0小时1分钟2秒",
    "activityName": "数据处理",
    "startTime": "2020-05-20 16:13:50",
    "assignee": "ass001",
    "endTime": "2020-05-20 16:14:53",
    "activityType": "用户处理",
    "message": "无"
}, {
    
    "costTime": "0天0小时1分钟25秒",
    "activityName": "审批",
    "startTime": "2020-05-20 16:14:53",
    "assignee": "0000",
    "endTime": "2020-05-20 16:16:18",
    "activityType": "用户处理",
    "message": "驳回原因:数据又遗漏"
}, {
    
    "costTime": "0天0小时0分钟25秒",
    "activityName": "数据处理",
    "startTime": "2020-05-20 16:16:18",
    "assignee": "ass001",
    "endTime": "2020-05-20 16:16:44",
    "activityType": "用户处理",
    "message": "无"
}, {
    
    "costTime": "0天0小时0分钟19秒",
    "activityName": "审批",
    "startTime": "2020-05-20 16:16:44",
    "assignee": "0000",
    "endTime": "2020-05-20 16:17:03",
    "activityType": "用户处理",
    "message": "驳回原因:数据有空值"
}, {
    
    "costTime": "0天0小时0分钟5秒",
    "activityName": "数据处理",
    "startTime": "2020-05-20 16:17:03",
    "assignee": "ass001",
    "endTime": "2020-05-20 16:17:08",
    "activityType": "用户处理",
    "message": "无"
}, {
    
    "costTime": "0天0小时0分钟19秒",
    "activityName": "审批",
    "startTime": "2020-05-20 16:17:08",
    "assignee": "0000",
    "endTime": "2020-05-20 16:17:28",
    "activityType": "用户处理",
    "message": "数据审批通过"
}, {
    
    "costTime": "0天0小时0分钟0秒",
    "activityName": "结束",
    "startTime": "2020-05-20 16:17:28",
    "assignee": "无",
    "endTime": "2020-05-20 16:17:28",
    "activityType": "流程结束",
    "message": "无"
}]

十三、删除流程数据语句

use workflow;
set sql_safe_updates=0;

DELETE FROM act_hi_actinst;
DELETE FROM act_hi_comment;
DELETE FROM act_hi_op_log;
DELETE FROM act_hi_procinst;
DELETE FROM act_hi_taskinst;
DELETE FROM act_hi_varinst;

DELETE FROM act_ge_bytearray;

DELETE FROM act_ru_task;
DELETE FROM act_ru_variable;
DELETE FROM act_ru_execution;

DELETE FROM act_re_deployment;
DELETE FROM act_re_procdef;

如果遇到外键约束检查:

SET foreign_key_checks = 0;
-- delete sql script 
SET foreign_key_checks = 1;

代码参考:https://github.com/zhoupengwa/ProcessEngineDemo

删除某一个流程实例相关的数据(最后两个表是我自己加的)


USE workflow;
SET sql_safe_updates=0;
SET FOREIGN_KEY_CHECKS=0;

DELETE FROM ACT_HI_ACTINST WHERE ROOT_PROC_INST_ID_='8607';
DELETE FROM ACT_HI_COMMENT WHERE PROC_INST_ID_='8607';
DELETE FROM ACT_HI_OP_LOG WHERE ROOT_PROC_INST_ID_='8607' OR PROC_INST_ID_='8607';
DELETE FROM ACT_HI_PROCINST WHERE ID_='8607';
DELETE FROM ACT_HI_TASKINST WHERE ROOT_PROC_INST_ID_='8607';
DELETE FROM ACT_HI_VARINST WHERE ROOT_PROC_INST_ID_='8607';

DELETE FROM ACT_GE_BYTEARRAY WHERE ROOT_PROC_INST_ID_='8607';

DELETE FROM ACT_RU_TASK WHERE PROC_INST_ID_='8607';
DELETE FROM ACT_RU_VARIABLE WHERE PROC_INST_ID_='8607';
DELETE FROM ACT_RU_EXECUTION WHERE ROOT_PROC_INST_ID_='8607' OR PROC_INST_ID_='8607';

DELETE FROM ACT_HI_IDENTITYLINK WHERE ROOT_PROC_INST_ID_='8607';



-- 清理自定义的一些表
delete from act_custom_user_process_filter where process_instance_id='8607';
delete from act_custom_audit_oper_log where process_instance_id = '8607';
delete from act_custom_reject_record where process_instance_id = '8607';


SET FOREIGN_KEY_CHECKS=1;


学习来源:腾讯课堂

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_35890572/article/details/114676357

智能推荐

使用 arm-linux-androideabi-addr2line 工具定位 libunity.so 崩溃问题-程序员宅基地

文章浏览阅读710次,点赞13次,收藏7次。它的名称有点不同 - aarch64-linux-android-addr2line。尽管该实用程序的名称不包含单词arm,但它成功地解密了arm64-v8下的堆栈跟踪,并通常感知arm64-v8的字符。是 NDK 自带的调试工具,可以用来分析 so 崩溃时输出的的内存地址。之后就是通过 cmd 进入到这个路径。找到了 64 位所需的实用程序。_arm-linux-androideabi

javaweb-邮件发送_javaweb发送邮件-程序员宅基地

javaweb-邮件发送 摘要: 本文介绍了邮件传输协议(SMTP和POP3)以及电子邮件的发送和接收过程。还讨论了纯文本文件、带图片和附件的邮件发送方法,以及通过servlet方式注册邮箱和使用springboot框架发送邮件的实现。

element-ui table 设置表格滚动条位置_element table 滚动条位置-程序员宅基地

文章浏览阅读4.3k次,点赞6次,收藏11次。在切换不同页面时(被 keep-alive 缓存的组件间切换),页面中的element-ui table的滚动条位置没有停留在原来的位置。目前需要切换不同的页面返回来后,滚动条保持在原来的位置。_element table 滚动条位置

前端开发经验总结_属性值[session.getattribute("strpath")]引用["],在值内使用时必须-程序员宅基地

文章浏览阅读2.6k次。 我设置nowrap和不设置nowrap效果都一样。就是表格随着文字自动伸展,为什么? →回答问题:TD元素noWrap属性的行为与TD元素的width属性有关。 ◆如果未设置TD宽度,则noWrap属性是起作用的。◆如果设置了TD宽度,则noWrap属性是不起作用的。 http://www.blueidea.com/tech/web/2003/943.as_属性值[session.getattribute("strpath")]引用["],在值内使用时必须被转义。

JS如何把Object对象的数据输出到控制台中_前端怎么通过控制台查看字段取值-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏3次。 前端时间在编写程序时遇到这样一个问题,即在前端页面通过一些js框架自带的异步请求返回的数据类型为Object数据类型,笔者根据网上查阅到的资料,找到以下这种简单的方式://把Object类型转为Json数据格式,再通过console命令在控制台中打印出来console.log("xhr的值为:"+JSON.st..._前端怎么通过控制台查看字段取值

8.cc.Button组件使用详解_cc button.start-程序员宅基地

文章浏览阅读556次。1. cc.Button添加按钮的方法 2种方式 (1)直接创建带Button组件的节点; (2) 先创建节点,再添加组件;按钮组件, 按钮是游戏中最常用的组件, 点击然后响应事件;按钮的过渡效果: 过渡: 普通状态, 鼠标滑动到物体上, 按下状态, 禁用状态 (1)没有过渡,只有响应事件; (2)颜色过渡, 过渡效果中使用颜色; (3)精灵..._cc button.start

随便推点

计算机专业游戏本推荐,2018高性价比游戏本推荐_游戏笔记本哪个好-太平洋电脑网...-程序员宅基地

文章浏览阅读245次。【PConline海选导购】晃眼间,秋风又起,让人振奋的开学季又要到来了!虽然说没有学习压力的暑假,在家着实悠哉,但想到回校后可以跟小伙伴们一起各种开黑吃鸡,是不是就感到很兴奋呢?说到“吃鸡”这种吃配置的游戏,就不得不说游戏本了,毕竟普通的笔记本电脑很难给我们带来畅快的游戏体验。而近年来游戏本市场俨然成为了各大厂商的必争之地,而随着开学季的到来,各大厂商更是推出了众多促销活动,下面就让我们一起来看..._计应专业游戏本

codePen按钮样式学习

看到codepen里面有的按钮搞得很炫酷,但其实也不是很难,就学习记录一下。

服务器维护中没法直播游戏,我的世界盒子显示维护中如何进入战堂服务器-程序员宅基地

文章浏览阅读408次。时间:2021-08-11编辑:hxh斗罗大陆魂师对决火雨队怎么搭配?火雨队是近期非常热门的一套阵容,不少玩家想了解该阵容,那么下面就让小编给大家带来斗罗大陆魂师对决火雨队阵容推荐,感兴趣的小伙伴们一起来看看吧。时间:2021-08-11编辑:hxh玩家在巅峰演武副本中不知道怎么打秦明,秦明的盾很厚不知道怎么破?那么下面就让小编给大家带来斗罗大陆魂师对决巅峰演武秦明破盾攻略,感兴趣的小伙伴们一起来...

GNU Radio之Schmidl & Cox OFDM synch.底层C++实现

在 GNU Radio OFDM 系统中,一个非常重要的环节是在接收端准确地同步和检测发送端发出的信号。这就是 Schmidl & Cox 同步算法发挥作用的地方。Schmidl & Cox 算法是一种用于 OFDM 信号的时间同步的技术。本文对其底层 C++ 源码进行学习记录。

项目开发规范

REST,表述性状态转换,他是一种软件架构风格使用URL定位资源,HTTP动词描述操作根据发出请求类型来区分操作此为风格,是约定方式,可以打破描述模块的功能通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。

3.8设计模式——State 状态模式(行为型)

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。