Activiti 6中的可插拔持久性
在過去的幾年中,我們經常聽到(來自社區和我們的客戶)關于如何將Activiti的持久性邏輯從關系數據庫交換到其他內容的請求。 當我們宣布Activiti 6時, 我們做出的承諾之一就是我們將實現這一目標。
深入研究Activiti引擎代碼的人會知道,這是認真的重構,因為持久性代碼與常規邏輯緊密結合。 基本上,在Activiti v5中,有:
- 實體類 :這些實體類包含數據庫中的數據。 通常,一個數據庫行是一個實體實例
- EntityManager :這些類將與實體相關的操作分組(查找,刪除等)
- DbSqlSession :使用MyBatis的低級操作(CRUD)。 還包含命令持續時間緩存,并管理數據到數據庫的刷新。
版本5中的問題如下:
- 沒有接口。 一切都是一類,因此替換邏輯變得非常困難。
- 在整個代碼庫中到處都使用了低級DbSqlSession。
- 很多關于實體的邏輯載的實體類中 。 例如,查看TaskEntity complete方法。 您不必是Activiti專家即可了解這不是一個不錯的設計:
- 觸發一個事件
現在不要誤會我的意思。 v5代碼將我們帶到了很遠的地方,并為世界各地許多出色的功能提供了支持。 但是,當涉及到交換持久層時……這并不值得驕傲。
并且可以肯定,我們可以闖入版本5代碼(例如,通過用響應于那里使用的方法/查詢名稱的自定義東西換出DbSqlSession),但這仍然不是很好的設計方法和非常像關系數據庫。 而且這不一定與您可能使用的數據存儲技術匹配。
不, 對于版本6,我們希望正確執行 。 而且,天哪……我們知道這將需要大量工作……但是它的工作量超出了我們的想象(只需查看過去幾周內v6分支上的提交 )。 但是我們做到了……最終的結果很美 (我有偏見,是的)。 因此,讓我們看一下v6中的新架構(請原諒我的powerpoint圖片。我是編碼人員,而不是設計師!):
因此,在v5中沒有接口的地方,在v6中到處都有接口。 上面的結構適用于引擎中的所有Entity類型 (當前為25個左右)。 因此,例如對于TaskEntity ,有一個TaskEntityImpl , TaskEntityManager , TaskEntityManagerImpl , TaskDataManager和TaskDataManagerImpl類(是的,我知道,他們仍然需要javadoc)。 這適用于所有實體。
讓我解釋一下上圖:
- EntityManager :這是與數據有關的所有其他代碼都可以與之通信的接口。 當涉及特定實體類型的數據時,它是唯一的入口點。
- EntityManagerImpl : EntityManager類的實現。這些操作通常是高層的,并且同時執行多項操作。 例如,執行刪除可能還會刪除任務,作業,identityLinks等并觸發相關事件。 每個EntityManager實現都有一個DataManager。 每當需要持久性存儲中的數據時,它就使用此DataManager實例獲取或寫入相關數據。
- DataManager:此接口包含“低級”操作。 通常包含針對其管理的實體類型的CRUD方法以及需要特定用例數據時的特定查找方法
- DataManagerImpl :DataManager接口的實現。 包含實際的持久性代碼。 在v6中,這是唯一現在使用DbSqlSession類通過MyBatis與數據庫進行通信的類。 通常,這是您要換出的班級。
- 實體 :數據接口。 僅包含getter和setter。
- EntityImpl :上述接口的實現。 在Activiti v6中,這是常規的pojo,但是該界面允許您切換到其他技術,例如帶有spring-dataj,JPA,…(使用批注)的Neo4。 沒有它,如果默認實現在您的持久性技術上不起作用,則需要包裝/拆開實體。
合并
將所有操作移入接口可以使我們清楚地了解在代碼庫中分布了哪些方法。 例如,您是否知道至少有五種不同的方法來刪除執行(名為“刪除”,“刪除”,“銷毀”等)? 他們所做的幾乎相同,但有細微的差別。 有時甚至一點都不微妙。
過去幾周的許多工作包括將所有這些邏輯整合為一種方法。 現在,在當前的代碼庫中,只有一種方法可以執行某些操作。 對于想使用不同持久性技術的人來說,這非常重要。 使它們實現所有變體和微妙之處將是瘋狂的。
內存中實現
為了證明持久層的可插入性,我制作了一個小的“內存中”原型。 這意味著,我們使用普通的舊式HashMaps代替關系數據庫來將實體存儲為{entityId,Entitys}。 然后查詢成為if子句。
- 可以在Github上找到代碼: https : //github.com/jbarrez/activiti-in-mem-prototype
(有時在論壇上,人們問到僅在內存中運行Activiti會有多困難,對于那些不要求使用數據庫的簡單用例來說。現在,這不再困難了!誰知道……這個小原型如果人們喜歡,它可能會變成東西!)
- 如預期的那樣,我們用內存中的版本換出了DataManager實現,請參閱InMemoryProcessEngineConfiguration
這樣的DataManager實現非常簡單。 例如,請參閱InMemoryTaskDataManager ,它需要為TaskEntity實現數據檢索/寫入方法:
public List<TaskEntity> findTasksByExecutionId(String executionId) {List<TaskEntity> results = new ArrayList<TaskEntity>();for (TaskEntity taskEntity : entities.values()) {if (taskEntity.getExecutionId() != null && taskEntity.getExecutionId().equals(executionId)) {results.add(taskEntity);}}return results;}為了證明它是可行的,讓我們進行部署,啟動一個簡單的流程實例,進行一些小任務查詢并檢查一些歷史記錄。 此代碼與“常規” Activiti用法完全相同。
public class Main {public static void main(String[] args) {InMemoryProcessEngineConfiguration config = new InMemoryProcessEngineConfiguration();ProcessEngine processEngine = config.buildProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();RuntimeService runtimeService = processEngine.getRuntimeService();TaskService taskService = processEngine.getTaskService();HistoryService historyService = processEngine.getHistoryService();Deployment deployment = repositoryService.createDeployment().addClasspathResource("oneTaskProcess.bpmn20.xml").deploy();System.out.println("Process deployed! Deployment id is " + deployment.getId());ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();System.out.println("Got " + tasks.size() + " tasks!");taskService.complete(tasks.get(0).getId());System.out.println("Number of process instances = " + historyService.createHistoricProcessInstanceQuery().count());System.out.println("Number of active process instances = " + historyService.createHistoricProcessInstanceQuery().finished().count());System.out.println("Number of finished process instances = " + historyService.createHistoricProcessInstanceQuery().unfinished().count());}}如果運行它,它可以為您提供這一切(非常快,因為它們全部在內存中!):
Process deployed! Deployment id is 27073df8-5d54-11e5-973b-a8206642f7c5Got 1 tasks!Number of process instances = 1Number of active process instances = 0Number of finished process instances = 1在這個原型中,我沒有添加事務語義。 這意味著,如果兩個用戶將同時完成同一用戶任務,那么結果將是不確定的。 當然,您可能希望從Activiti API獲得類似內存中事務的邏輯,但是我尚未實現。 基本上,您需要將所有接觸的對象保留在一個小的緩存中,直到刷新/提交時間,然后在該位置進行一些鎖定/同步。 當然,我確實接受拉取請求:)
下一步是什么?
好吧,這完全取決于您。 讓我們知道您對此有何想法,請嘗試一下!
我們與計劃很快試用的社區成員/客戶之一保持著密切聯系。 但是我們當然也想自己玩這個游戲,我們正在尋找一個很酷的首選(我自己在Neo4j的心中仍然占有特殊的位置 ……這很適合交易)。
但是最重??要的一點是:在Activiti v6中,現在可以干凈地交換持久層。 我們為現在的外觀感到自豪。 我們希望您也喜歡它!
翻譯自: https://www.javacodegeeks.com/2015/09/pluggable-persistence-in-activiti-6.html
總結
以上是生活随笔為你收集整理的Activiti 6中的可插拔持久性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 6217993000哪个银行?
- 下一篇: 华商银行是工商银行吗?