上文提到,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>

  减少一个实体管理器,将表单数据映射成实体类并存入库。

@Servicepublic 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层代码:

@Servicepublic 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")@RestControllerpublic 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@Transactionalclass 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的继承,把表单数据保留到自定义的表中,不仅把原来“无构造”的数据转换为“有构造”的数据,还缩小了变量表的数据量,进步了数据的查问、应用效率。