返回介绍

10.3. 使用

发布于 2023-09-17 23:40:35 字数 5589 浏览 0 评论 0 收藏 0

10.3.1. 简单示例

可以在Flowable源代码的JPAVariableTest中找到使用JPA变量的例子。下面逐步解释JPAVariableTest.testUpdateJPAEntityValues

首先,基于META-INF/persistence.xml为持久化单元创建EntityManagerFactory。包括需要包含在持久化单元内的类及一些(数据库)厂商特定配置。

在这个测试里使用的是简单实体,包括id以及一个String值参数。在运行测试前,先创建一个实体并保存。

@Entity(name = "JPA_ENTITY_FIELD")
public class FieldAccessJPAEntity {

  @Id
  @Column(name = "ID_")
  private Long id;

  private String value;

  public FieldAccessJPAEntity() {
  // JPA需要的空构造方法
  }

  public Long getId() {
  return id;
  }

  public void setId(Long id) {
  this.id = id;
  }

  public String getValue() {
  return value;
  }

  public void setValue(String value) {
  this.value = value;
  }
}

启动一个新的流程实例,将这个实体加入变量。与其他变量一样,它们都会在引擎中持久化存储。当下一次请求这个变量时,将会根据类及Id,从EntityManager载入。

Map<String, Object> variables = new HashMap<String, Object>();
variables.put("entityToUpdate", entityToUpdate);

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
  "UpdateJPAValuesProcess", variables);

流程定义的第一个节点是服务任务,将调用entityToUpdate上的setValue方法。entityToUpdate将解析为之前启动流程实例时设置的JPA变量,并使用当前引擎的上下文中关联的EntityManager载入。

<serviceTask id='theTask' name='updateJPAEntityTask'
  flowable:expression="${entityToUpdate.setValue('updatedValue')}" />

当服务任务完成时,流程实例在流程定义中的用户任务处等待,以便我们可以查看流程实例。在这时,EntityManager已经刷入,对实体的修改也已经存入数据库。当获取entityToUpdate变量的值时,将重新载入实体。所以可以得到value参数设置为updatedValue的实体。

// 流程'UpdateJPAValuesProcess'中的服务任务已经设置了entityToUpdate的值。
Object updatedEntity = runtimeService.getVariable(processInstance.getId(), "entityToUpdate");
assertTrue(updatedEntity instanceof FieldAccessJPAEntity);
assertEquals("updatedValue", ((FieldAccessJPAEntity)updatedEntity).getValue());

10.3.2. 查询JPA流程变量

可以查询以特定JPA实体作为变量值的流程实例执行请注意ProcessInstanceQueryExecutionQuery中,只有variableValueEquals(name, entity)方法支持JPA实体查询。而variableValueNotEqualsvariableValueGreaterThanvariableValueGreaterThanOrEqualvariableValueLessThanvariableValueLessThanOrEqual等方法都不支持JPA,并会在值传递为JPA实体时,抛出FlowableException

 ProcessInstance result = runtimeService.createProcessInstanceQuery()
  .variableValueEquals("entityToQuery", entityToQuery).singleResult();

10.3.3. 使用Spring bean与JPA的高级示例

可以在flowable-spring-examples中找到高级用法的示例——JPASpringTest。它描述了一个简单的用例:

  • 使用一个已有的Spring bean及已定义的JPA实体,用于存储贷款申请。

  • Flowable通过该bean获取该实体,并将其用作流程中的变量。流程定义如下步骤:

    • 使用LoanRequestBean,并使用启动流程时(从启动表单)接收的变量创建LoanRequest(贷款申请)实体的服务任务。使用flowable:resultVariable将表达式结果,即所创建的实体存储为流程变量。

    • 经理用于审核并批准/驳回申请的用户任务,并将审核结论存储为boolean变量approvedByManager

    • 更新贷款申请实体的服务任务,使实体与流程同步。

    • 使用一个排他网关,依据approved实体参数的值选择下一步采用哪条路径:若申请被批准,结束流程;否则,生成一个额外任务(Send rejection letter 发送拒信),以便客户可以收到拒信得到通知。

请注意这个流程只用于单元测试,而不包含任何表单。

jpa.spring.example.process
<?xml version="1.0" encoding="UTF-8"?>
<definitions
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:flowable="http://flowable.org/bpmn"
  targetNamespace="org.flowable.examples">

  <process name="Process creating and handling loan request">
  <startEvent id='theStart' />
  <sequenceFlow id='flow1' sourceRef='theStart' targetRef='createLoanRequest' />

  <serviceTask id='createLoanRequest' name='Create loan request'
    flowable:expression="${loanRequestBean.newLoanRequest(customerName, amount)}"
    flowable:resultVariable="loanRequest"/>
  <sequenceFlow id='flow2' sourceRef='createLoanRequest' targetRef='approveTask' />

  <userTask name="Approve request" />
  <sequenceFlow id='flow3' sourceRef='approveTask' targetRef='approveOrDissaprove' />

  <serviceTask id='approveOrDissaprove' name='Store decision'
    flowable:expression="${loanRequest.setApproved(approvedByManager)}" />
  <sequenceFlow id='flow4' sourceRef='approveOrDissaprove' targetRef='exclusiveGw' />

  <exclusiveGateway name="Exclusive Gateway approval" />
  <sequenceFlow sourceRef="exclusiveGw" targetRef="theEnd">
    <conditionExpression xsi:type="tFormalExpression">${loanRequest.approved}</conditionExpression>
  </sequenceFlow>
  <sequenceFlow sourceRef="exclusiveGw" targetRef="sendRejectionLetter">
    <conditionExpression xsi:type="tFormalExpression">${!loanRequest.approved}</conditionExpression>
  </sequenceFlow>

  <userTask name="Send rejection letter" />
  <sequenceFlow id='flow5' sourceRef='sendRejectionLetter' targetRef='theOtherEnd' />

  <endEvent id='theEnd' />
  <endEvent id='theOtherEnd' />
  </process>

</definitions>

尽管上面的例子很简单,但也展示了JPA与Spring结合,以及带参数方法表达式的威力。这个流程本身完全不需要写Java代码(当然还是需要写Spring bean),大幅加速了开发。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文