Flowable variable operation and pit row

Mainly understand the knowledge points
insert image description here

1. Name Explanation

Explain the difference between Portal
setVariables and setVariablesLocal in detail?

1. Process variables
are used to set and obtain variables during process execution or task execution, and use process variables to transfer business parameters during process delivery.
Corresponding table:
act_ru_variable: process variable table being executed
act_hi_varinst: process variable history table

2. The difference between setVariable and setVariableLocal

setVariable: When setting a process variable, when the name of the process variable is the same, the value of the last time will replace the value of the previous time, and you can see that the TASK_ID field will not store the value of the task ID

setVariableLocal:

1) When setting the process variable, set the process variable for the currently active node. If there are 2 active nodes in a process, set the process variable for each active node. Even if the name of the process variable is the same, the value of the later version will not replace the value of the previous version. It will use a different task ID as an identifier to store 2 process variable values, and you can see that the TASK_ID field will store the value of the task ID.

For example, the data of the act_hi_varinst table: different task nodes, even if the name of the process variable is the same, the stored values ​​are different.

2) Also, use setVariableLocal to indicate that the process variable is bound to the current task. When the process continues to execute, the next task cannot obtain this process variable (because there is no such data in the process variable being executed), and all the tasks that are being executed cannot be queried. The data we need cannot be queried. At this time, we need to query the historical process variables.

It can be simply considered that variables are all for processInstance.

Local may be for an execution branch or for a task.

Here we will talk about the scope of variables. Variables must exist attached to the concepts in a certain process, so these variables can be used in the process of process flow.

The default variables are at the process instance level, that is to say, both branch execution and task can read the variables in the corresponding processInstance.

The opposite is the local variable, which is simply not a variable in the scope of processInstance. How to distinguish between global and local? The difference is that the scope of local is small. If it is a local variable of branch execution, it can only be used during the lifetime of the execution branch.

For example, when the concurrent branch ends, the variable is gone.

For example, when the task is over, the variables are gone.

The advantage of local variables is that variables with the same name can be used in each branch without affecting each other. The countersign multi-instance is realized through local local variables.

After the process instance ends, the process variables are still stored in the database (stored in the history table of the process variables).

   1)流程变量的作用域就是流程实例,所以只要设置就行了,不用管在哪个阶段设置

   2)基本类型设置流程变量,在taskService中使用任务ID,定义流程变量的名称,设置流程变量的值

   3)Javabean类型设置流程变量,需要这个javabean实现了Serializable接口

    4)设置流程变量的时候,向act_ru_variable这个表添加数据

    5)流程变量的获取针对流程实例(1个流程),每个流程实例获取的流程变量是不同的

    6)使用基本类型获取流程变量,在taskService中使用任务ID,流程变量的名称,获取流程变量的值。

    7)Javabean类型设置获取流程变量,除了需要这个javabean实现了Serializable接口外,还要求流程变量对象的属性不能发生变化,否则抛出异常。解决方案,固定序列化ID

Two, practical operation

test common code

 ProcessEngineConfiguration configuration= null;

    @Before
    public void before(){
        //获取 ProcessEngineConfiguration 对象
        configuration = new StandaloneProcessEngineConfiguration();
        // 配置数据库连接信息
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
        //如果数据库中不存在表结构就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    }

    @Test
    public void test(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //完成流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("test.bpmn20.xml")
                .name("测试流程 部署")
                .deploy();
        System.out.println("deployment.getName() : " + deployment.getName());
        System.out.println("deployment.getId() : " + deployment.getId());
    }

Pay attention to a small detail first

ProcessInstance instance1 = runtimeService.createProcessInstanceQuery().processInstanceId("75001").singleResult();
 System.out.println("instance1 proVar: "+instance.getProcessVariables()); // 结果{}

Why instance.getProcessVariables() is empty

This question starts with the model.
Flowable implements a command mode by itself. All operations are realized through the command mode. The advantage of the command mode is that the environment can be opened before the command is executed, and the environment can be closed after the naming.
Unfortunately, flowable opens jdbc and closes jdbc in this way.
Therefore, once jdbc is closed, that is, after cmd is executed, the database cannot be operated. It does not have the function of OpenSessionInVIew like hibernate.
Therefore, you must tell flowable that you need to fetch variables before cmd is executed, otherwise it will not search at all, and if you do not send sql, even if there are variables in the database, they will not be fetched.
The way to tell flowable is through includeProcessVariables.
For example, runtimeService.createProcessInstanceQuery().includeProcessVariables().list() has variables.
For example, runtimeService.createProcessInstanceQuery().list() has no variables.

1. Substitution rules for global variables

    @Test
    public void test02(){
    
    
        ProcessEngine processEngine = configuration.buildProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> var = new HashMap<>();
        var.put("test","申请变量");
        ProcessInstance instance = runtimeService.startProcessInstanceById("test:2:47504",var);
        Map<String, Object> variables = new HashMap<>();
//        variables.put("Local","proInst");
        variables.put("test","proInst");
        runtimeService.setVariables(instance.getId(),variables);
        System.out.println(" instanceid: "+instance.getId());
        
    }
    
        @Test
    public void complete(){
    
    

        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance instance1 = runtimeService.createProcessInstanceQuery().processInstanceId("77501").includeProcessVariables().singleResult();
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId("77501").includeProcessVariables().singleResult();
        System.out.println("instance proVar: "+instance.getProcessVariables());
        System.out.println("instance1 proVar: "+instance1.getProcessVariables());
        // instance proVar: {test=proInst}
// instance1 proVar: {test=proInst}

    }

The result is replaced by the following value, if one of them is set as a local variable, it will not be replaced == runtimeService.setVariablesLocal(instance.getId(),variables); ==

2. Task variables

code practice


	// 设置流程变量
    @Test
    public void test02(){
    
    
        ProcessEngine processEngine = configuration.buildProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> var = new HashMap<>();
        var.put("test","申请变量");
        ProcessInstance instance = runtimeService.startProcessInstanceById("test:2:47504",var);
        Map<String, Object> variables = new HashMap<>();
        variables.put("Local","proInst");
        runtimeService.setVariablesLocal(instance.getId(),variables);
        System.out.println(" instanceid: "+instance.getId());
        // 1. 50001 2. 57501 3. 62501 4.70001 5.
    }
    
    // 完成任务,同时设置任务的局部变量
    @Test
    public void complete(){
    
    

        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 62501  局部70001  全局72501
//        ProcessInstance instance1 = runtimeService.createProcessInstanceQuery().processInstanceId("77501").includeProcessVariables().singleResult();
//        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId("77501").includeProcessVariables().singleResult();
//        System.out.println("instance proVar: "+instance.getProcessVariables());
//        System.out.println("instance1 proVar: "+instance1.getProcessVariables());
        Map<String, Object> var = new HashMap<>();
        // 如果scope 为false,则任务变量都是空的,只有统一的流程实例变量
        var.put("complete","完成任务65003的变量,scope true");
        taskService.complete("65003",var,true);

    }

	//	查看变量
    @Test
    public void var(){
    
    

        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        HistoryService historyService = processEngine.getHistoryService();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId("62501")
                .includeProcessVariables()
                .singleResult();
//        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId("50001").singleResult();
        System.out.println("流程实例 ProcessVariables: "+historicProcessInstance.getProcessVariables());


        List<HistoricVariableInstance> list1 = historyService.createHistoricVariableInstanceQuery().processInstanceId("62501").list();
        System.out.println("流程实例变量 =================== ");
        list1.forEach(item -> {
    
    
            System.out.println("name: "+item.getVariableName());
            System.out.println("value: "+item.getValue());
        });
        System.out.println("流程实例变量 =================== ");

        // ("50006");
        List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().taskId("62506").list();
        System.out.println("任务1的变量 =================== ");
        list.forEach(item -> {
    
    
            System.out.println(item.getVariableName());
            System.out.println(item.getValue());
        });
        System.out.println("任务1的变量 =================== ");
        List<HistoricVariableInstance> list2 = historyService.createHistoricVariableInstanceQuery().taskId("65003").list();
        System.out.println("任务2的变量 =================== ");
        list2.forEach(item -> {
    
    
            System.out.println(item.getVariableName());
            System.out.println(item.getValue());
        });
        System.out.println("任务2的变量 =================== ");
//        Map<String, Object> variables02 = taskService.getVariables("52503");
//        System.out.println("任务2的变量: "+variables02);
//        Map<String, Object> var = new HashMap<>();
//        var.put("complete","完成任务50006的变量");
//        taskService.complete("50006",var);


        /**
         * 流程实例 ProcessVariables: {test=申请变量, Local=proInst}
         * 流程实例变量 =================== 
         * name: test
         * value: 申请变量
         * name: Local
         * value: proInst
         * name: complete
         * value: 完成任务62506的变量,scope true
         * name: complete
         * value: 完成任务65003的变量,scope true
         * 流程实例变量 =================== 
         * 任务1的变量 =================== 
         * complete
         * 完成任务62506的变量,scope true
         * 任务1的变量 =================== 
         * 任务2的变量 =================== 
         * complete
         * 完成任务65003的变量,scope true
         * 任务2的变量 =================== 
         */
    }


result

insert image description here

taskService.complete(“65003”,var,true)

complete can increase the environment variables of each task (that is, a task is associated with some unique variables), such as a task with a form, scope should be set to true (true is local, false is global [default])

When scope is true

insert image description here
The historical variable table will be associated with taskid

When scope is false

insert image description here
The historical variable table will not be associated with taskid, it is an instance global variable, and the problem of replacing the variable value before it will occur

Guess you like

Origin blog.csdn.net/weixin_43861630/article/details/129056964