共计 6825 个字符,预计需要花费 18 分钟才能阅读完成。
上文提到,Flowable 所有的表单数据都保留在一张表(act_hi_varinst)中,随着工夫的推移,表中数据越来越多,再加上数据没有构造优化,查问应用效率会越来越低。
在 Flowable,能够通过集成 JPA 解决上述问题。JPA 把表单数据保留在用户自定义的表中,有利于查问优化。
一、什么是 JPA
JPA 是 Java Persistence API 的简称,中文名 Java 长久层 API,是 JDK 5.0 注解或 XML 形容对象-关系表的映射关系,并将运行期的实体对象长久化到数据库中。
JPA 在大多数零碎中曾经失去广泛应用,越来越多的开源框架公布了本人的 JPA 实现,例如 Hibernate、Open JPA、Spring Data 等。
二、JPA 反对
在 Springboot 中,为 Flowable 增加 JPA 反对,减少下列依赖:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring.boot.version}</version>
</dependency>
这会退出 JPA 用的 Spring 配置以及 bean。默认应用 Hibernate 作为 JPA 提供者。
留神:JPA 只是接口标准,没有具体实现,与 Flowable 应用的 ORM 框架 MyBatis 并无抵触。
在 classpath 的 application.properties 文件退出下列参数,主动创立数据库表。
spring.jpa.hibernate.ddl-auto=update
另外,举荐援用 lombok 包,能够让咱们省去实体类写 Getter 和 Setter 办法的工作。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
三、JPA 版本的销假流程
3.1 简略的销假流程
咱们以一个简略的销假流程为实例阐明 JPA 的具体应用。该销假实例只有一个用户工作,由用户填写表单数据,发动一个销假流程实例,后交由部门经理 leader 审批。
销假流程图示:
流程定义 leave-process.bpmn20.xml
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:flowable="http://flowable.org/bpmn"
targetNamespace="Examples">
<process id="leaveProcess" name="The leave Process" >
<startEvent id="theStart" flowable:formKey="leave">
<extensionElements>
<flowable:executionListener event="start" expression="${execution.setVariable('leave', leaveEntityManager.newLeave(execution))}}">
</flowable:executionListener>
</extensionElements>
</startEvent>
<sequenceFlow sourceRef="theStart" targetRef="theLeaderApprove" />
<userTask id="theLeaderApprove" name="部门经理审批" flowable:candidateGroups="leader">
<extensionElements>
<flowable:taskListener event="complete" expression="${leave.setLeaderApproved(leaderApproved)}">
</flowable:taskListener>
</extensionElements>
</userTask>
<sequenceFlow sourceRef="theLeaderApprove" targetRef="theEnd" />
<endEvent id="theEnd" >
<extensionElements>
<flowable:executionListener event="end" delegateExpression="${leaveEndListener}">
</flowable:executionListener>
</extensionElements>
</endEvent>
</process>
</definitions>
销假表单 leave.form
{
"key": "leave",
"name": "销假流程",
"fields": [
{
"id": "startTime",
"name": "开始工夫",
"type": "date",
"required": true,
"placeholder": "empty"
},
{
"id": "endTime",
"name": "完结工夫",
"type": "date",
"required": true,
"placeholder": "empty"
},
{
"id": "reason",
"name": "销假起因",
"type": "text",
"required": true,
"placeholder": "empty"
}
]
}
3.2 启动流程时长久化 JPA 实体
定义一个销假申请表单类
@Data
@Entity(name="event_leave")
public class LeaveEntity implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String processInstanceId;
private LocalDate StartTime;
private LocalDate endTime;
private String reason;
private String leaderApproved;
}
留神:Flowable 表单类型“Date”映射的是 org.joda.time.LocalDate 类,并不是 JDK8 自带的 java.time.LocalDate 类。
在流程中配置一个 start 类型的监听器,作用是读取用户填写的表单内容并创立实体类对象长久化到数据库中。
批改 XML 内容:
<startEvent id="theStart" flowable:formKey="leave">
<extensionElements>
<flowable:executionListener event="start" expression="${execution.setVariable('leave', leaveEntityManager.newLeave(execution))}}">
</flowable:executionListener>
</extensionElements>
</startEvent>
减少一个实体管理器,将表单数据映射成实体类并存入库。
@Service
public class LeaveEntityManager {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public LeaveEntity newLeave(DelegateExecution execution) {LeaveEntity leave = new LeaveEntity();
leave.setProcessInstanceId(execution.getProcessInstanceId());
leave.setStartTime((LocalDate)execution.getVariable("startTime"));
leave.setEndTime((LocalDate)execution.getVariable("endTime"));
leave.setReason(execution.getVariable("reason").toString());
entityManager.persist(leave);
return leave;
}
}
上面展现填写表单,启动流程的具体代码。
Service 层代码:
@Service
public class jpaService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private RepositoryService repositoryService;
@Transactional
public void startProcess() {List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("leaveProcess").orderByProcessDefinitionId().desc().list();
String proDefId = processDefinitionList.get(0).getId();
Map<String, Object> formProp = new HashMap();
formProp.put("reason", "家里有事");
formProp.put("startTime", LocalDate.now());
formProp.put("endTime", LocalDate.now());
String outcome = "outStr";
runtimeService.startProcessInstanceWithForm(proDefId, outcome, formProp, "表单工作");
}
}
Controller 层代码:
@RequestMapping("/jpa")
@RestController
public class jpaController {
@Autowired
private jpaService myService;
@RequestMapping(value="/process", method= RequestMethod.POST)
public void startProcessInstance() {myService.startProcess();
}
}
启动利用后,应用 cURL 测试:
curl http://localhost:8080/jpa/process
这样在流程启动后查问数据表 event_leave 就看到一条数据:
咱们再来察看运行时变量表:
变量表.png
能够看到变量“leave”的类型字段(TYPE-)为“jpa-entity”,该记录的“TEXT-”、“TEXT2-“字段别离代表实体的残缺类名和主键 ID。
3.3 更改 JPA 实体属性
在流程运行时,如果用户在办理时填写了工作表单,那么还须要把改变的数据更新到实体中,比方:部门领导审核节点实现时保留审批意见。
同样的,在用户工作上增加一个 complete 类型的监听器。
批改 XML 内容:
<userTask id="theLeaderApprove" name="部门经理审批" flowable:candidateGroups="leader">
<extensionElements>
<flowable:taskListener event="complete" expression="${leave.setLeaderApproved(leaderApproved)}">
</flowable:taskListener>
</extensionElements>
</userTask>
Service 层减少办法:
@Transactional
public void complete(String groupName) {List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup(groupName).orderByTaskCreateTime().desc().list();
String taskId = taskList.get(0).getId();
Map<String, Object> param = new HashMap();
param.put("leaderApproved", true);
taskService.complete(taskId, param);
}
Controller 层减少办法:
@RequestMapping(value="/complete", method= RequestMethod.GET, produces= MediaType.APPLICATION_JSON_VALUE)
public void complete(@RequestParam String groupName) {myService.complete(groupName);
}
应用 cURL 测试:
http://localhost:8080/jpa/complete?groupName=leader
查看销假表数据:
销假表 2.png
同样变量表中的值也被批改。
下面咱们只是设置了变量值,没有批改数据库,为什么就达到了批改实体属性的目标呢?这是因为 Springboot 曾经帮咱们配置了事务管理器,即由 Springboot 接管了 Flowable 的事务,当更改实体属性并提交事务时,就主动执行了数据库的 update 操作。
3.4 清理历史表单数据
当初咱们曾经胜利把表单数据独自保留在用户自定义表中,但还有一个问题没有解决,那就是把历史变量表的对应数据删除,给历史变量表瘦身,进步查问效率。
同样的,咱们设置一个 end 类型的监听器清理历史表单数据。
批改 XML 内容:
<endEvent id="theEnd" >
<extensionElements>
<flowable:executionListener event="end" delegateExpression="${leaveEndListener}">
</flowable:executionListener>
</extensionElements>
</endEvent>
leaveEndListener 是一个 service 类,内容是把历史变量表 act_hi_varinst 中对应的变量数据删除。
@Service
@Transactional
class LeaveEndListener implements ExecutionListener {
@PersistenceContext
private EntityManager entityManager;
@Override
public void notify(DelegateExecution execution) {String processInstanceId = execution.getProcessInstanceId();
String sql = "delete from act_hi_varinst where proc_inst_id_ = ?";
entityManager.createNativeQuery(sql).setParameter(1, processInstanceId).executeUpdate();}
}
四、小结
本篇具体介绍了 Flowable 与 JPA 的继承,把表单数据保留到自定义的表中,不仅把原来“无构造”的数据转换为“有构造”的数据,还缩小了变量表的数据量,进步了数据的查问、应用效率。