Flowable流程开发笔记

Flowable 流程引擎开发笔记

常用表

运行时表(流程运行中才有数据,结束后自动清理)

表名 存什么 说明
ACT_RU_TASK 当前待办任务 ASSIGNEE_ 为 null 表示在候选人池,有值表示已被认领
ACT_RU_IDENTITYLINK 任务的候选人/参与者 TYPE_ = candidate 是候选人,assignee 是指派人
ACT_RU_VARIABLE 流程变量 存流程实例级别的变量数据
ACT_RU_EXECUTION 流程执行实例 一个流程实例可能有多条执行线(会签时)
ACT_RU_ACTINST 当前活跃的活动节点 当前流程走到哪个节点了

历史表(流程结束后数据移到这些表)

表名 存什么 说明
ACT_HI_TASKINST 所有任务(含已完成的) 流程的所有审批记录都在这里
ACT_HI_PROCINST 所有流程实例 START_USER_ID_ 是发起人
ACT_HI_ACTINST 所有活动节点历史 每个节点的开始、结束时间
ACT_HI_VARINST 历史流程变量 流程变量变更记录

其他

表名 存什么 说明
ACT_RE_PROCDEF 流程定义 部署的 BPMN 模型
ACT_RE_DEPLOYMENT 部署记录 每次发布流程的版本

常用查询

找当前待办

sql 复制代码
-- 查某人的待办
SELECT * FROM ACT_RU_TASK WHERE ASSIGNEE_ = 'loginName';

-- 查候选人池里的任务
SELECT * FROM ACT_RU_TASK WHERE ASSIGNEE_ IS NULL;

查候选人

sql 复制代码
-- 查某个 task 的所有候选人
SELECT * FROM ACT_RU_IDENTITYLINK 
WHERE TASK_ID_ = 'taskId' AND TYPE_ = 'candidate';

-- 查 group 下的候选人
SELECT * FROM ACT_RU_IDENTITYLINK 
WHERE GROUP_ID_ = 'groupId' AND TYPE_ = 'candidate';

查流程历史

sql 复制代码
-- 查某个流程实例的所有审批记录
SELECT * FROM ACT_HI_TASKINST 
WHERE PROC_INST_ID_ = '流程实例ID' 
ORDER BY START_TIME_;

-- 查某人发起的所有流程
SELECT * FROM ACT_HI_PROCINST WHERE START_USER_ID_ = 'loginName';

TaskTransferService

java 复制代码
package com.oda.apps.iplm.service.impl;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class TaskTransferService {

    @Autowired
    private TaskService taskService;

    /**
     * 直接转办给新人(适用于已签收/认领的任务)
     */
    @Transactional(rollbackFor = Exception.class)
    public void reassign(String taskId, String newAssignee) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) throw new RuntimeException("任务不存在:" + taskId);

        taskService.setAssignee(taskId, newAssignee);
        taskService.addComment(taskId, task.getProcessInstanceId(),
                "转办:" + task.getAssignee() + " → " + newAssignee);
        log.info("转办 {}/{} : {} → {}", taskId, task.getName(), task.getAssignee(), newAssignee);
    }

    /**
     * 替换候选人池:移除旧人,加入新人
     * 适用场景:任务没人认领,离职的人从候选人池移除,新人加进去
     */
    @Transactional(rollbackFor = Exception.class)
    public void replaceCandidate(String taskId, String oldUser, String newUser) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) throw new RuntimeException("任务不存在:" + taskId);

        // 如果旧人已经签收了,一并转交
        if (StrUtil.isNotBlank(task.getAssignee()) && task.getAssignee().equals(oldUser)) {
            taskService.setAssignee(taskId, newUser);
        }

        taskService.deleteCandidateUser(taskId, oldUser);
        taskService.addCandidateUser(taskId, newUser);
        taskService.addComment(taskId, task.getProcessInstanceId(),
                "候选人变更:" + oldUser + " → " + newUser);
        log.info("候选人变更 {}/{} : {} → {}", taskId, task.getName(), oldUser, newUser);
    }

    /**
     * 通过流程实例ID转办
     */
    @Transactional(rollbackFor = Exception.class)
    public void transferByProcessInstance(String processInstanceId, String oldUser, String newUser) {
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .active()
                .list();

        for (Task task : tasks) {
            if (StrUtil.isNotBlank(task.getAssignee()) && task.getAssignee().equals(oldUser)) {
                taskService.setAssignee(task.getId(), newUser);
            }
            taskService.deleteCandidateUser(task.getId(), oldUser);
            taskService.addCandidateUser(task.getId(), newUser);
        }
        log.info("流程 {} 转办:{} → {}", processInstanceId, oldUser, newUser);
    }
}

调用方式

java 复制代码
@Autowired
private TaskTransferService taskTransferService;

// 场景一:任务已被离职的人签收,直接转给新人
taskTransferService.reassign(taskId, "新人LoginName");

// 场景二:任务还在候选人池,替换候选人
taskTransferService.replaceCandidate(taskId, "离职人LoginName", "新人LoginName");

// 场景三:只有流程实例ID,不知道taskId
taskTransferService.transferByProcessInstance(processInstanceId, "离职人LoginName", "新人LoginName");

几个概念

概念 说明
taskId 任务ID,具体某个审批节点的ID,ACT_RU_TASK.ID_
processInstanceId 流程实例ID,整条审批的ID,createWorkflow 的返回值
assignee 指派人,任务被谁签收了,不为 null 表示有人认领了
candidate 候选人,任务可以被这些人处理,谁先点谁签收
claim 签收/认领,候选人把任务拿到自己名下,之后只有他能处理
签收 vs 未签收 assignee 有值=签收了,null=还没人认领
相关推荐
自不量力的A同学1 天前
LibreOffice 26.2.5 发布
笔记
依然范特东1 天前
强化学习笔记5--值函数近似、policy gradient
笔记
星恒随风1 天前
C++ STL 详解:map 与 multimap 的使用、operator[]
开发语言·c++·笔记·学习·状态模式
@Mike@1 天前
05-数据库学习笔记(缓冲池优化和存储模型)
数据库·笔记·学习
九硕智慧建筑一体化厂家1 天前
直流照明|社区公共空间智慧便民照明方案
笔记·智慧城市
摇滚侠1 天前
Codebuddy 官网 Codebuddy IntelliJ IDEA 插件 阅读笔记 1
java·笔记·intellij-idea
九硕智慧建筑一体化厂家1 天前
直流照明|酒店民宿温馨智能照明方案
笔记·智慧城市
Zzj_tju1 天前
如何写论文复现笔记:从 Reproduction Report 到博客草稿
笔记
IT古董1 天前
【MES学习笔记系列】02 - MES 需求分析
笔记·学习·需求分析