Flowable 6.6.0 BPMN用户指南 - 17 高级用例 - 17.5 执行自定义SQL(Execute custom SQL)

《Flowable 6.6.0 BPMN用户指南》

1. 入门
2. 配置
3 The Flowable API
4 Flowable 6.6.0 BPMN用户指南 - (4)Spring集成
5 Spring Boot
6 部署
7 BPMN 2.0简介
8 BPMN 2.0的构造
9 表单(Forms)
10 流程实例迁移
11 JPA
12 历史(History)
13 身份管理(Identity management)
14 REST API
15 CDI集成
16 LDAP集成
17 高级用例
  • 17.1 异步执行器(Async Executor)
    • 17.1.1 异步执行器设计(Async Executor design)
    • 17.1.2 异步执行器配置
    • 17.1.3 基于异步执行器的消息队列
  • 17.2 与流程解析挂钩(Hooking into process parsing)
  • 17.3 用于高并发的UUID ID生成器
  • 17.4 多租户(Multitenancy)
  • 17.5 执行自定义SQL(Execute custom SQL)
  • 17.6 采用ProcessEngineConfigurator 进行高级的流程引擎配置
  • 17.7 高级查询API:运行时和历史任务查询之间的无缝切换
  • 17.8 重写标准SessionFactory实现自定义身份管理
  • 17.9 启用安全的BPMN 2.0 xml
  • 17.10 事件日志记录(Event logging)
  • 17.11 禁用批量插入(Disabling bulk inserts)
  • 17.12 安全脚本(Secure Scripting)
  • 17.13 日志记录会话[实验性]

有关Flowable的更多文档,参见:

《Flowable文档大全》


17.5 执行自定义SQL(Execute custom SQL)

The Flowable API allows for interacting with the database using a high level API. For example, for retrieving data the Query API and the Native Query API are powerful in its usage. However, for some use cases they might not be flexible enough. The following section describes how a completely custom SQL statement (select, insert, update and delete are possible) can be executed against the Flowable data store, but completely within the configured Process Engine (and thus levering the transaction setup for example).

To define custom SQL statements, the Flowable engine leverages the capabilities of its underlying framework, MyBatis. More info can be read in the MyBatis user guide.

Flowable API允许使用高级API(high level API)与数据库交互。例如,对于检索数据,Query API和Native Query API的用法非常强大。然而,对于某些用例,它们可能不够灵活。以下部分描述如何针对可流动数据存储执行完全自定义的SQL语句(可以查询、插入、更新和删除),但完全在配置的流程引擎中执行(例如,还可以利用事务设置)。

为了定义定制的SQL语句,Flowable引擎利用其底层框架MyBatis的功能。更多信息可在MyBatis用户指南(in the MyBatis user guide)中阅读。

17.5.1 基于注解的映射语句(Annotation based Mapped Statements)

The first thing to do when using Annotation based Mapped Statements, is to create a MyBatis mapper class. For example, suppose that for some use case not the whole task data is needed, but only a small subset of it. A Mapper that could do this, looks as follows:

使用基于注解的映射语句(Annotation based Mapped Statements)时,首先要做的是创建一个MyBatis映射器类。例如,假设对于某些用例,不需要整个任务数据,而只需要其中的一小部分。以下Mapper可以做到:

public interface MyTestMapper {
     

    @Select("SELECT ID_ as id, NAME_ as name, CREATE_TIME_ as createTime FROM ACT_RU_TASK")
    List<Map<String, Object>> selectTasks();

}

This mapper must be provided to the Process Engine configuration as follows:

此映射器必须提供给流程引擎配置,如下所示:

...
<property name="customMybatisMappers">
  <set>
    <value>org.flowable.standalone.cfg.MyTestMapper</value>
  </set>
</property>
...

Notice that this is an interface. The underlying MyBatis framework will make an instance of it that can be used at runtime. Also notice that the return value of the method is not typed, but a list of maps (which corresponds to the list of rows with column values). Typing is possible with the MyBatis mappers if wanted.

To execute the query above, the managementService.executeCustomSql method must be used. This method takes in a CustomSqlExecution instance. This is a wrapper that hides the internal bits of the engine otherwise needed to make it work.

Unfortunately, Java generics make it a bit less readable than it could have been. The two generic types below are the mapper class and the return type class. However, the actual logic is simply to call the mapper method and return its results (if applicable).

注意这是一个接口。底层MyBatis框架将生成一个可以在运行时使用的实例。还要注意,该方法的返回值不是类型化的,而是一个映射列表(对应于具有列值的行的列表)。如果需要的话,可以MyBatis映射器可以类型化(Typing)。

若要执行上述查询,则必须使用managementService.executeCustomSql 方法。此方法接受一个CustomSqlExecution 实例。这是一个包装器,它隐藏了使之工作的引擎的内部部分信息。

不幸的是,Java泛型使得它的可读性比原来的要低一些。下面的两个泛型类型是映射器类(mapper class)和返回类型类(return type class)。然而,实际的逻辑只是调用映射器方法并返回其结果(如果适用)。

CustomSqlExecution<MyTestMapper, List<Map<String, Object>>> customSqlExecution =
          new AbstractCustomSqlExecution<MyTestMapper, List<Map<String, Object>>>(MyTestMapper.class) {
     

  public List<Map<String, Object>> execute(MyTestMapper customMapper) {
     
    return customMapper.selectTasks();
  }

};

List<Map<String, Object>> results = managementService.executeCustomSql(customSqlExecution);

The Map entries in the list above will only contain id, name and create time in this case and not the full task object.

Any SQL is possible when using the approach above. Another more complex example:

在本例中,上面列表中的Map条目只包含id、name和create time,而没有包含完整的task对象。

使用上述方法时,可以使用任何SQL。另一个更复杂的例子:

    @Select({
     
        "SELECT task.ID_ as taskId, variable.LONG_ as variableValue FROM ACT_RU_VARIABLE variable",
        "inner join ACT_RU_TASK task on variable.TASK_ID_ = task.ID_",
        "where variable.NAME_ = #{variableName}"
    })
    List<Map<String, Object>> selectTaskWithSpecificVariable(String variableName);

Using this method, the task table will be joined with the variables table. Only where the variable has a certain name is retained, and the task id and the corresponding numerical value is returned.

For a working example on using Annotation based Mapped Statements check the unit test org.flowable.standalone.cfg.CustomMybatisMapperTest and other classes and resources in folders src/test/java/org/flowable/standalone/cfg/ and src/test/resources/org/flowable/standalone/cfg/

使用此方法,任务表将与变量表联接。只有在变量具有特定名称的情况下才会保留,并返回任务id和相应的数值。
有关使用基于注解的映射语句的工作示例,请检查单元测试org.flowable.standalone.cfg.CustomMybatisMapperTest以及src/test/java/org/flowable/standalone/cfg/和src/test/resources/org/flowable/standalone/cfg/文件夹中的其他类和资源

17.5.2 基于XML的映射语句(XML based Mapped Statements)

When using XML based Mapped Statements, statements are defined in XML files. For the use case where not the whole task data is needed, but only a small subset of it. The XML file can look as follows:

使用基于XML的映射语句时,语句是在XML文件中定义的。对于不需要整个任务数据的用例,只需要其中一小部分数据。XML文件可以如下所示:

<mapper namespace="org.flowable.standalone.cfg.TaskMapper">

  <resultMap id="customTaskResultMap" type="org.flowable.standalone.cfg.CustomTask">
    <id property="id" column="ID_" jdbcType="VARCHAR"/>
    <result property="name" column="NAME_" jdbcType="VARCHAR"/>
    <result property="createTime" column="CREATE_TIME_" jdbcType="TIMESTAMP" />
  </resultMap>

  <select id="selectCustomTaskList" resultMap="customTaskResultMap">
    select RES.ID_, RES.NAME_, RES.CREATE_TIME_ from ACT_RU_TASK RES
  </select>

</mapper>

Results are mapped to instances of org.flowable.standalone.cfg.CustomTask class which can look as follows:
结果映射到org.flowable.standalone.cfg.CustomTask类,如下所示:


public class CustomTask {
     

  protected String id;
  protected String name;
  protected Date createTime;

  public String getId() {
     
    return id;
  }
  public String getName() {
     
    return name;
  }
  public Date getCreateTime() {
     
    return createTime;
  }
}

Mapper XML files must be provided to the Process Engine configuration as follows:

映射器XML文件必须提供给流程引擎配置,如下所示:

...
<property name="customMybatisXMLMappers">
  <set>
    <value>org/flowable/standalone/cfg/custom-mappers/CustomTaskMapper.xml</value>
  </set>
</property>
...

The statement can be executed as follows:

语句的执行方式如下:

List<CustomTask> tasks = managementService.executeCommand(new Command<List<CustomTask>>() {
     

      @SuppressWarnings("unchecked")
      @Override
      public List<CustomTask> execute(CommandContext commandContext) {
     
        return (List<CustomTask>) commandContext.getDbSqlSession().selectList("selectCustomTaskList");
      }
    });

For uses cases that require more complicated statements, XML Mapped Statements can be helpful. Since Flowable uses XML Mapped Statements internally, it’s possible to make use of the underlying capabilities.

Suppose that for some use case the ability to query attachments data is required based on id, name, type, userId, etc! To fulfill the use case a query class AttachmentQuery that extends org.flowable.engine.impl.AbstractQuery can be created as follows:

对于需要更复杂语句的用例,XML映射语句可能很有用。由于Flowable在内部使用XML映射语句,所以可以使用底层功能。

假设对于某些用例,需要根据id、name、type、userId等查询附件数据!为了实现这个用例,查询类AttachmentQuery 扩展org.flowable.engine.impl.AbstractQuery,可以按如下方式创建:


public class AttachmentQuery extends AbstractQuery<AttachmentQuery, Attachment> {
     

  protected String attachmentId;
  protected String attachmentName;
  protected String attachmentType;
  protected String userId;

  public AttachmentQuery(ManagementService managementService) {
     
    super(managementService);
  }

  public AttachmentQuery attachmentId(String attachmentId){
     
    this.attachmentId = attachmentId;
    return this;
  }

  public AttachmentQuery attachmentName(String attachmentName){
     
    this.attachmentName = attachmentName;
    return this;
  }

  public AttachmentQuery attachmentType(String attachmentType){
     
    this.attachmentType = attachmentType;
    return this;
  }

  public AttachmentQuery userId(String userId){
     
    this.userId = userId;
    return this;
  }

  @Override
  public long executeCount(CommandContext commandContext) {
     
    return (Long) commandContext.getDbSqlSession()
                   .selectOne("selectAttachmentCountByQueryCriteria", this);
  }

  @Override
  public List<Attachment> executeList(CommandContext commandContext, Page page) {
     
    return commandContext.getDbSqlSession()
            .selectList("selectAttachmentByQueryCriteria", this);
  }

Note that when extending AbstractQuery extended classes should pass an instance of ManagementService to super constructor and methods executeCount and executeList need to be implemented to call the mapped statements.

The XML file containing the mapped statements can look as follows:

请注意,在扩展AbstractQuery 时,扩展类应该将ManagementService 的实例传递给超级构造函数(super constructor),并且需要实现executeCount 和executeList 方法来调用映射的语句。
包含映射语句的XML文件可以如下所示:

<mapper namespace="org.flowable.standalone.cfg.AttachmentMapper">

  <select id="selectAttachmentCountByQueryCriteria" parameterType="org.flowable.standalone.cfg.AttachmentQuery" resultType="long">
    select count(distinct RES.ID_)
    <include refid="selectAttachmentByQueryCriteriaSql"/>
  </select>

  <select id="selectAttachmentByQueryCriteria" parameterType="org.flowable.standalone.cfg.AttachmentQuery" resultMap="org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap">
    ${limitBefore}
    select distinct RES.* ${limitBetween}
    <include refid="selectAttachmentByQueryCriteriaSql"/>
    ${orderBy}
    ${limitAfter}
  </select>

  <sql id="selectAttachmentByQueryCriteriaSql">
  from ${prefix}ACT_HI_ATTACHMENT RES
  <where>
   <if test="attachmentId != null">
     RES.ID_ = #{attachmentId}
   </if>
   <if test="attachmentName != null">
     and RES.NAME_ = #{attachmentName}
   </if>
   <if test="attachmentType != null">
     and RES.TYPE_ = #{attachmentType}
   </if>
   <if test="userId != null">
     and RES.USER_ID_ = #{userId}
   </if>
  </where>
  </sql>
</mapper>

Capabilities such as pagination, ordering, table name prefixing are available and can be used in the statements (since the parameterType is a subclass of AbstractQuery). Note that to map results the predefined org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap resultMap can be used.

Finally, the AttachmentQuery can be used as follows:

分页、排序、表名前缀等功能都是可用的,可以在语句中使用(因为parameterType是AbstractQuery的一个子类)。请注意,要映射结果,可以使用预定义的org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap resultMap。
最后,AttachmentQuery 的用法如下:

....
// Get the total number of attachments
long count = new AttachmentQuery(managementService).count();

// Get attachment with id 10025
Attachment attachment = new AttachmentQuery(managementService).attachmentId("10025").singleResult();

// Get first 10 attachments
List<Attachment> attachments = new AttachmentQuery(managementService).listPage(0, 10);

// Get all attachments uploaded by user kermit
attachments = new AttachmentQuery(managementService).userId("kermit").list();
....

For working examples on using XML Mapped Statements check the unit test org.flowable.standalone.cfg.CustomMybatisXMLMapperTest and other classes and resources in folders src/test/java/org/flowable/standalone/cfg/ and src/test/resources/org/flowable/standalone/cfg/

使用XML映射语句的示例可检查位于src/test/java/org/flowable/standalone/cfg/和src/test/resources/org/flowable/standalone/cfg/文件夹中的单元测试org.flowable.standalone.cfg.CustomMybatisXMLMapperTest 以及其他类和资源。

你可能感兴趣的:(Flowable,6.6.0,BPMN用户指南,-9-18)