??上文提到,F(xiàn)lowable所有的表單數(shù)據(jù)都保存在一張表(act_hi_varinst)中驰贷,隨著時間的推移鲸睛,表中數(shù)據(jù)越來越多,再加上數(shù)據(jù)沒有結(jié)構(gòu)優(yōu)化关划,查詢使用效率會越來越低膘融。
??在Flowable,可以通過集成JPA解決上述問題祭玉。JPA把表單數(shù)據(jù)保存在用戶自定義的表中氧映,有利于查詢優(yōu)化。
一脱货、什么是JPA
??JPA是Java Persistence API的簡稱岛都,中文名Java持久層API,是JDK 5.0注解或XML描述對象-關(guān)系表的映射關(guān)系振峻,并將運行期的實體對象持久化到數(shù)據(jù)庫中臼疫。
??JPA在大多數(shù)系統(tǒng)中已經(jīng)得到廣泛應(yīng)用,越來越多的開源框架發(fā)布了自己的JPA實現(xiàn)扣孟,例如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富蓄。默認(rèn)使用Hibernate作為JPA提供者剩燥。
注意:JPA只是接口規(guī)范,沒有具體實現(xiàn)立倍,與Flowable使用的ORM框架MyBatis并無沖突灭红。
??在classpath的application.properties文件加入下列參數(shù),自動創(chuàng)建數(shù)據(jù)庫表口注。
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的具體使用。該請假實例只有一個用戶任務(wù)澈段,由用戶填寫表單數(shù)據(jù)悠菜,發(fā)起一個請假流程實例,后交由部門經(jīng)理leader審批败富。
??請假流程圖示:
請假流程.png
??流程定義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">
</startEvent>
<sequenceFlow sourceRef="theStart" targetRef="theLeaderApprove" />
<userTask id="theLeaderApprove" name="部門經(jīng)理審批" flowable:candidateGroups="leader">
</userTask>
<sequenceFlow sourceRef="theLeaderApprove" targetRef="theEnd" />
<endEvent id="theEnd" >
</endEvent>
</process>
</definitions>
??請假表單leave.form
{
"key": "leave",
"name": "請假流程",
"fields": [
{
"id": "startTime",
"name": "開始時間",
"type": "date",
"required": true,
"placeholder": "empty"
},
{
"id": "endTime",
"name": "結(jié)束時間",
"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類型的監(jiān)聽器兽叮,作用是讀取用戶填寫的表單內(nèi)容并創(chuàng)建實體類對象持久化到數(shù)據(jù)庫中芬骄。
??修改XML內(nèi)容:
<startEvent id="theStart" flowable:formKey="leave">
<extensionElements>
<flowable:executionListener event="start" expression="${execution.setVariable('leave', leaveEntityManager.newLeave(execution))}}">
</flowable:executionListener>
</extensionElements>
</startEvent>
??增加一個實體管理器,將表單數(shù)據(jù)映射成實體類并存入庫鹦聪。
@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, "表單任務(wù)");
}
}
??Controller層代碼:
@RequestMapping("/jpa")
@RestController
public class jpaController {
@Autowired
private jpaService myService;
@RequestMapping(value="/process", method= RequestMethod.POST)
public void startProcessInstance() {
myService.startProcess();
}
}
??啟動應(yīng)用后泽本,使用cURL測試:
curl http://localhost:8080/jpa/process
??這樣在流程啟動后查詢數(shù)據(jù)表event_leave就看到一條數(shù)據(jù):
請假表.png
??我們再來觀察運行時變量表:
變量表.png
??可以看到變量“l(fā)eave”的類型字段(TYPE-)為“jpa-entity”淘太,該記錄的“TEXT-”、“TEXT2-“字段分別代表實體的完整類名和主鍵ID规丽。
3.3 更改JPA實體屬性
??在流程運行時蒲牧,如果用戶在辦理時填寫了任務(wù)表單,那么還需要把改動的數(shù)據(jù)更新到實體中赌莺,比如:部門領(lǐng)導(dǎo)審核節(jié)點完成時保存審批意見冰抢。
??同樣的,在用戶任務(wù)上添加一個complete類型的監(jiān)聽器艘狭。
??修改XML內(nèi)容:
<userTask id="theLeaderApprove" name="部門經(jīng)理審批" 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
??查看請假表數(shù)據(jù):
請假表2.png
??同樣變量表中的值也被修改挎扰。
??上面我們只是設(shè)置了變量值翠订,沒有修改數(shù)據(jù)庫,為什么就達(dá)到了修改實體屬性的目的呢遵倦?這是因為Springboot已經(jīng)幫我們配置了事務(wù)管理器尽超,即由Springboot接管了Flowable的事務(wù),當(dāng)更改實體屬性并提交事務(wù)時骇吭,就自動執(zhí)行了數(shù)據(jù)庫的update操作橙弱。
3.4 清理歷史表單數(shù)據(jù)
??現(xiàn)在我們已經(jīng)成功把表單數(shù)據(jù)單獨保存在用戶自定義表中歧寺,但還有一個問題沒有解決燥狰,那就是把歷史變量表的對應(yīng)數(shù)據(jù)刪除,給歷史變量表瘦身斜筐,提高查詢效率龙致。
??同樣的,我們設(shè)置一個end類型的監(jiān)聽器清理歷史表單數(shù)據(jù)顷链。
??修改XML內(nèi)容:
<endEvent id="theEnd" >
<extensionElements>
<flowable:executionListener event="end" delegateExpression="${leaveEndListener}">
</flowable:executionListener>
</extensionElements>
</endEvent>
??leaveEndListener是一個service類目代,內(nèi)容是把歷史變量表act_hi_varinst中對應(yīng)的變量數(shù)據(jù)刪除。
@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();
}
}
四嗤练、小結(jié)
??本篇詳細(xì)介紹了Flowable與JPA的繼承榛了,把表單數(shù)據(jù)保存到自定義的表中,不僅把原來“無結(jié)構(gòu)”的數(shù)據(jù)轉(zhuǎn)換為“有結(jié)構(gòu)”的數(shù)據(jù)煞抬,還減少了變量表的數(shù)據(jù)量霜大,提高了數(shù)據(jù)的查詢、使用效率革答。