Camunda流程引擎底层采用了mybatis作为ORM框架,并封装了一套自己的数据查询接口,以下是几种可以Camunda流程引擎中查询数据的方式。
- Java 查询API 。使用 Fluent Java API 来查询流程引擎实体,比如流程实例、任务等。
- REST 查询API 。通过 REST API 来查询流程引擎实体,比如流程实例、任务等。
- 原生查询。如果缺乏需要的查询能力(比如 OR 条件查询),可以提供自定义的 SQL 查询语句来查询流程引擎实体,比如流程实例、任务等。
- 定制化查询。使用完全定制的查询和自己的 MyBatis 映射来查询对象,或者使用领域数据来连接到流程引擎。
- SQL 查询。使用数据库的 SQL 语句查询功能。
根据项目需求,可以使用其中的任意一种查询 API ,优先推荐Camunda自己封装的Fluent API进行数据查询。
1. Java 查询API
可以使用 Fluent API 来编写类型安全的查询。可以在查询中添加各种条件(所有这些条件一起通过逻辑与( AND )使用),并且按照明确的顺序进行排序。
【例1】查询 API 的示例,代码如下:
List <Task> tasks = taskService.createTaskQuery().taskAssignee ("zhangs").processVariablevalueEquals ("orderId ","1001").orderByDueDate(). asc ().list();
在默认情况下,查询 API 把所有的过滤条件通过逻辑与连接起来。此外,逻辑或(OR )查询使得所有过滤条件可以通过逻辑或连接起来。
注意:逻辑或查询只适用于任务查询。不适用于逻辑或查询的有 orderBy...0、 initializeFormKeys()、withCandidateGroups()、withoutCandidateGroups()、 withCandidateUsers ()、withoutCandidateUsers ()。
在调用or方法后,后面可以跟着一系列的过滤条件,每一个过滤条件都是通过 OR 表达式连接起来的。调用 endOr ()方法标志着结束 OR 查询。调用这两个方法相当于把过滤条件放在了括号中。
【例2】 OR 查询示例。
List <Task> tasks = takService.createTaskQuery().taskAssignee ("zhangs"). or().taskName ("Approve Invoice ").taskPriority (5).endOr ().list ();
上述查询获取的是所有分配给 zhangs的任务,并且需要同时满足任务名是 Approve Invoice 或者任务优先级为5的情况。在流程引擎内部,上述查询会转化为如下简化的 SQL 查询,代码如下:
SELECT DISTINCT * FROM act_ru_task RES WHERE RES.assignee _=' zhangs' AND ( Upper ( RES.name )= Upper (' Approve Invoice ') OR RES.priority _=5);
在查询内部可以嵌入任意数量的 OR 查询。当构建的查询不仅包含单个 OR 查询,而且包含与 AND 表达式链接在一起的过滤条件时, AND 表达式将被放在前面,后面跟着 OR 查询。
与变量相关的过滤条件可以在 OR 查询中应用多次,代码如下:
List <Task> tasks = taskService.createTaskQuery ()·or()·processvariablevalueEquals ("orderId","9897").processvariableValueEquals("orderId","9898").processvariableValueEquals ("orderId ","9899").endOr().list();
除了与变量相关的过滤条件外,其他的行为是不同的。当在查询中使用非变量相关的过滤条件时,只有最后一个值会被真正使用到。非变量相关的查询示例,代码如下,
List <Task> tasks = taskService.createTaskQuery().or(). taskCandidateGroup ("sales").taskCandidateGroup ("controlling").end0r().list();
注意,上述例子中,过滤条件 taskCandidateGroup 中的 sales 被 controlling 替换掉了。为了避免这种情况,可以使用带 In 后缀的过滤条件,比如: taskCandidateGroupln(); tenantidin(); processDefinitionKeyln()。
2. REST 查询 API
Java 查询 API 也提供了 REST 服务接口。关于 REST 服务接口的详细信息,请参阅官网:https://docs.camunda.org/manual/7.15/reference/rest/。
3.原生数据库查询
在数据查询时可能需要更加强大的查询功能,比如使用 OR 运算符,或者是使用查询 API 没法表达的限制条件。在这种情况下,可以使用 Camunda 提供的原生数据库查询语言,也就是说,用户可以自己写 SQL 查询语句。返回类型由使用的查询对象定义,数据会被映射到正确的对象上去,比如任务、流程对象、执行等。由于查询要直接使用数据库,因此需要自己候要多加小心。数据库表名可以通过 API 获取。
使用数据库中定义的表名和列名。这就需要对内部数据结构有一定的了解。
原生数据库查询示例,代码如下:
List <Task> tasks = taskService.createNativeTaskQuery().sql (" SELECT count (*) FROM " + managementService.getTableName ( Task.class ) + " T WHERE T.NAME_ = #{ taskName }"). parameter (" taskName "," aOpenTask ").list();
4.自定义查询
为什么需要自定义查询?我们知道流程引擎提供了一个非常简单易用的Java Query API, 但对于复杂的业务查询还是不能满足,有时出于查询性能考虑,有时不需要查询引擎对象,而是需要查询自己的数据,或者关联业务表和流程引擎表查询数据,这时需要使用自定义查询。
比如: 业务系统里有一个自己的实体表“客户信息”,流程引擎里记录了customerId的流程变量“customer”,如果想做流程引擎实例数据和业务表数据的关联查询,就需要自定义查询。
详细见:https://camunda.com/blog/2017/12/custom-queries/
5.SQL查询
如果是仅仅要获取流程实例的数据,也可以直接查询Camunda表。比如:实现报表功能、流程数据同步等,可以直接使用 SQL 查询。