Flowable實戰(zhàn)(六)集成JPA

??上文提到,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ù)的查詢、使用效率。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容