Activiti中完全解決待辦事項列表查詢複雜、API不友好的設計方案

       咱們使用工做流引擎,一個很是重要的功能就是獲取待辦事項列表,在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視圖再查詢這些視圖。具體上開發者能夠靈活處理,本文再也不展開。

相關文章
相關標籤/搜索