咱們使用工做流引擎,一個很是重要的功能就是獲取待辦事項列表,在Activiti中,咱們能夠經過TaskService的相關API進行查詢,這些API設計優雅,可是實際使用中每每不夠方便,也缺少靈活性,達不到技術解決方案的要求,主要有以下幾個問題:數據庫
1.多數狀況沒法經過調用一個API知足需求,這時一個現實問題就是須要對結果集進行合併而後排序,這樣就顯得比較麻煩;設計
2.和項目業務表關聯困難;code
3.Activiti中相關查詢返回的是Activiti定義的實體,這些實體包含的信息可能不夠;對象
4.Activiti中的實體,可能和項目中的對象關係映射(ORM)衝突;排序
鑑於上述緣由,在一些大規模的項目中,Activiti提供的查詢API,實際使用價值不大,咱們須要另外尋找解決方案。在Activiti的查詢API中,也提供原始SQL的查詢接口,可是大量使用後,會發現代碼不夠優雅,維護困難。這個問題其實從開發者角度,查詢時用用戶的id,用最簡單的SQL查詢出來全部想要的信息是最理想的。接口
分析上述缺點和需求後,咱們認爲經過API方式進行查詢的話,老是有各類缺陷,所以把目標放在數據庫上,若是能經過定義視圖的方式解決問題,那麼將完全解決查詢的方便性、靈活性、通用性問題。開發
通過分析Activiti的數據庫表,咱們發現並不複雜,和待辦事項有關係的表,包括ACT_RU_TASK、ACT_RU_IDENTITYLINK,ACT_RU_TASK中存儲了任務相關信息,ACT_RU_IDENTITYLINK中存儲了候選組和候選人信息,這裏面一個比較重要的問題就是,Activiti中的候選組、候選人如何跟系統中的用戶、組織、角色對應的問題,本文提供的解決方案,假定系統中有一張名爲SYS_ROLE_USER的表,該表中存儲了角色和用戶的對應關係,而且Activiti中的候選組和角色是同一個概念,開發者的系統中具體是什麼狀況,須要開發者觸類旁通,本文僅提供一個設計思路。工作流
在Activiti中,對於一個節點,可分爲受託人,候選人和候選組三種狀況,後兩種能夠設置多個,用逗號分隔,對應到數據庫中,會被拆分爲ACT_RU_IDENTITYLINK的多條記錄,這些咱們都須要考慮,細節上能夠經過UNION實現,下面是樣例代碼,該代碼基於Oracle數據庫,其餘數據庫的版本,稍後會說明。it
CREATE VIEW V_TASKLIST AS SELECT A.ID_ AS TASK_ID, A.PROC_INST_ID_ PROC_INST_ID, A.TASK_DEF_KEY_ AS ACT_ID, A.NAME_ AS ACT_NAME, A.ASSIGNEE_ AS ASSIGNEE, A.DELEGATION_ AS DELEGATION_ID, A.DESCRIPTION_ AS DESCRIPTION, TO_CHAR(A.CREATE_TIME_, 'YYYY-MM-DD HH24:MI:SS') AS CREATE_TIME, TO_CHAR(A.DUE_DATE_,'YYYY-MM-DD HH24:MI:SS') AS DUE_DATE, I.USER_ID CANDIDATE FROM ACT_RU_TASK A LEFT JOIN (SELECT DISTINCT * FROM (SELECT TASK_ID_, TO_CHAR(USER_ID_) USER_ID FROM ACT_RU_IDENTITYLINK I, ACT_RU_TASK T WHERE TASK_ID_ IS NOT NULL AND USER_ID_ IS NOT NULL AND I.TASK_ID_ = T.ID_ AND T.ASSIGNEE_ IS NULL AND TYPE_ = 'candidate' UNION SELECT TASK_ID_, R.USER_ID FROM ACT_RU_IDENTITYLINK I,SYS_ROLE_USER R,ACT_RU_TASK T WHERE I.TASK_ID_ IS NOT NULL AND I.GROUP_ID_ IS NOT NULL AND I.TASK_ID_ = T.ID_ AND T.ASSIGNEE_ IS NULL AND TYPE_ = 'candidate' AND I.GROUP_ID_ = R.ROLE_ID)U) I--候選組和業務上的角色用戶表關聯 ON A.ID_ = I.TASK_ID_
這個視圖比較簡單,主要查詢了任務信息,若是還須要其餘信息,好比和流程實例、流程定義等,能夠自行增長其餘的表關聯,好比要和業務表關聯須要一個很重要的字段就是BUSINESS_KEY_,這個和ACT_RU_EXECUTION表關聯便可。date
這個視圖定義好以後,代辦查詢能夠用以下的更簡潔的SQL實現:
SELECT * FROM V_TASKLIST WHERE ASSIGNEE = :userId OR CANDIDATE = :userId
這樣的話,和業務表關聯也很是的方便,也不會受到API的限制,也不涉及和系統的ORM兼容的問題,基本上想查詢什麼信息就能用一個簡單的SQL查詢到什麼信息,基本能夠做爲一個通用的解決方案了。
上述例子僅提供了Oracle的代碼,對於兼容多數據庫的設計,比較麻煩,各類數據庫都對視圖的建立作了較多的限制,好比SQLServer不能在SQL中寫ORDER BY,MySQL中FROM字句不能嵌套子查詢,以及不一樣數據庫字段類型定義不一樣等,在咱們的解決方案中,基本上就是把上述SQL作了拆分,定義了若干很是小的視圖,而後V_TASKLIST視圖再查詢這些視圖。具體上開發者能夠靈活處理,本文再也不展開。