工做流性能優化(敢問activiti有擴展性?)(3)

2015/4/20java

週末回去想了下,hibernate、mybatis、jdbc,都行,最終定了用mybatis,誰叫它這麼優雅,acvtiviti是依賴了mybatis的,就不用再引入包了;node

看了配置文件,以前配置的是jpa,再配置mybatis,配置文件就顯得臃腫,很亂了;用jpa吧,貌似也不賴;mysql

clip_image002

 

再寫一個Repository;spring

寫SQL的時候用到了,知識點:sql

instr:instr(t.DESCRIPTION_, 'conditionCountersign') > 0數據庫

mysql查詢最後一條記錄,不能用orderby:tomcat

 

需求:要取a1的最後一條數據來關聯,語句以下;mybatis

解決:不能在inner join裏邊用order by xxx limit 1;架構

折中解決:用時間來限制;a1.START_TIME_>a2.START_TIME_app

select distinct RES.*, a1.ID_, a2.ID_ from ACT_HI_PROCINST RES inner join ACT_HI_ACTINST a1 on (a1.PROC_INST_ID_ = RES.PROC_INST_ID_ and a1.ACT_TYPE_ != 'endEvent')

inner join ACT_RU_TASK t on (a1.TASK_ID_=t.ID_ and instr(t.DESCRIPTION_, 'conditionCountersign') > 0)

inner join ACT_HI_ACTINST a2 on (a1.ACT_ID_=a2.ACT_ID_ and a1.START_TIME_>a2.START_TIME_ and a2.ASSIGNEE_='324')

where RES.END_TIME_ is null

and exists (select LINK.USER_ID_ from ACT_HI_IDENTITYLINK LINK where USER_ID_ = '324' and LINK.PROC_INST_ID_ = RES.ID_) order by START_TIME_ desc;

 

jpa映射activiti的實體,各類報錯;

clip_image003

好麻煩,jpa要寫實體,要寫HQL,原來我都寫好SQL了,還要轉換爲HQL,hibernate真麻煩;

慢慢拷貝表字段寫實體,每一個實體要繼承原有的entity;

 

先寫一個測試用例,跑通了再說,別連查詢都查不了,就浪費時間了;貼一些主要的代碼:

實體:

clip_image005

Repository:

clip_image007

測試用例:

clip_image009

能夠哦:

clip_image011

那開始慢慢寫實體吧,寫好再改HQL;

寫好了HQL,開始測試:

clip_image013

報錯:

Caused by: java.lang.IllegalArgumentException: node to traverse cannot be null!

摸不着頭腦,先精簡語句,先調通上半部分的union再說;

clip_image015

仍是同樣;

問度娘;度娘說是HQL寫錯了,哪裏錯了,她也不說,真是的;

再次精簡:

clip_image017

仍是同樣;

再次精簡:

clip_image019

仍是同樣;

哥,多了個左括號;繼續奮戰;

再加SQL:

clip_image021

加參數,加排序,很順利;

 

另外一個union問題就不少,有點絕望;

 

換用jdbc試試;

遇到的錯誤:

錯誤代碼: 1248

Every derived table must have its own alias

解決:

select count(0) as total from (xxx);後邊要帶別名;

select count(0) as total from (xxx) dd;

很快就寫好了,原生SQL就是好;

jdbc的dao層:

 

    /**
     * 分頁查詢待辦工做流記錄
     * @param involvedUser
     * @param firstResult
     * @param maxResults
     * @return
     */
    public List<HistoricProcessInstanceEntity> qryUnfinishedByInvolvedUser(HistoricProcessInstanceQuery query){
        StringBuilder sql = new StringBuilder();
        sql.append(" select  ");
        sql.append(HistoricProcessInstanceSQLFragment.baseColumnList());
        sql.append(" from (");
        sql.append("(select RES.* from ACT_HI_PROCINST RES ");
        sql.append("where RES.END_TIME_ is null ");
        sql.append("  and (exists (select LINK.USER_ID_ from ACT_HI_IDENTITYLINK LINK where USER_ID_ = ? and LINK.PROC_INST_ID_ = RES.PROC_INST_ID_)) ");
        sql.append("  and exists (select 1 from ACT_RU_TASK t where t.PROC_INST_ID_=RES.ID_ and t.ASSIGNEE_=? order by t.ID_ asc limit 1)) ");
        sql.append(" union ");
        sql.append(" (select distinct RES.* from ACT_HI_PROCINST RES inner join ACT_HI_ACTINST a1 on (a1.PROC_INST_ID_ = RES.PROC_INST_ID_ and a1.ACT_TYPE_ != 'endEvent') ");
        sql.append("     inner join ACT_RU_TASK t on (a1.TASK_ID_=t.ID_ and instr(t.DESCRIPTION_, 'conditionCountersign') > 0)  ");
        sql.append("     inner join ACT_HI_ACTINST a2 on (a1.ACT_ID_=a2.ACT_ID_ and a1.START_TIME_>a2.START_TIME_ and a2.ASSIGNEE_=?) ");
        sql.append("     where RES.END_TIME_ is null  ");
        sql.append("     and exists (select LINK.USER_ID_ from ACT_HI_IDENTITYLINK LINK where USER_ID_ = ? and LINK.PROC_INST_ID_ = RES.ID_)) ");
        sql.append("order by START_TIME_ desc) dd ");
        
        List<Object> param = new ArrayList<Object>();
        param.add(query.getInvolvedUser());
        param.add(query.getInvolvedUser());
        param.add(query.getInvolvedUser());
        param.add(query.getInvolvedUser());
        
        String countSql = PageUtils.getCountSQL(sql.toString());
        logger.info("About to excute sql=\n{}\n{}", countSql, BaseUtils.printList(param));
        Integer total = baseDao.getJdbcTemplate().queryForObject(countSql, param.toArray(), Integer.class);
        query.setTotalRecord(total);

        // 分頁設置
        PageUtils.buildPageSqlForMysql(sql, query);

        logger.info(" About to excute sql=\n{}\n{}", sql.toString(), BaseUtils.printList(param));
        List<HistoricProcessInstanceEntity> datas = baseDao.getJdbcTemplate().query(sql.toString(), param.toArray(), new BeanPropertyRowMapper<HistoricProcessInstanceEntity>(HistoricProcessInstanceEntity.class));
        return datas;
    }

 

 

 

啓動項目測試:

嚴重: Servlet.service() for servlet [spring] in context with path [] threw exception [Handler processing failed; nested exception is java.lang.NoSuchMethodError: com.sinotaiyo.srpm.activiti.DetailBuilder.BuildWorkflowDetailByEntity(Lorg/activiti/engine/impl/persistence/entity/HistoricProcessInstanceEntity;)Lcom/sinotaiyo/srpm/activiti/WorkflowDetail;] with root cause

java.lang.NoSuchMethodError: com.sinotaiyo.srpm.activiti.DetailBuilder.BuildWorkflowDetailByEntity(Lorg/activiti/engine/impl/persistence/entity/HistoricProcessInstanceEntity;)Lcom/sinotaiyo/srpm/activiti/WorkflowDetail;

方法是寫好的,debug進去是用代理模式;

javap –s DetailBuilder

clip_image025

貌似同樣的啊;

 

折騰了很久,用Run As Server裏邊的tomcat就能夠,但用maven插件的方式啓動就報錯;

爲啥呢?

優化到此爲止,告一段落。

疑問:

一、jpa的註解方式寫DAO層能夠用原生SQL嗎?HQL是這樣的:

clip_image027

二、activiti的表字段和屬性名雖然不同,但仍是能夠識別,不算折磨人,爲何不能同樣呢?同樣不是更好嗎?全部地方均可以拷貝,不用拷貝了修改,保留下劃線能夠理解,要是怕字段過長的話,別定那麼長的字段就能夠了,至少要保持一致,一致以後不少自動化的事情就好辦了,好比寫代碼生成器;

clip_image028

三、設計良好的數據庫,即便再複雜的查詢也應該是很好寫,爲什麼這裏的待辦查詢這麼恐怖?

總結:

一、 新入職,接手已有項目,就是這麼坎坷,習慣就好;

二、 論測試的重要性,一個語句測多少遍才測通啊,寫測試仍是很是有必要的,負責任的提現,但以前公司的開發人員,工做1年就當技術主管,代碼都沒寫幾行就主管,真心無語,還有個工做1年就封爲架構師,寫個JavaBean屬性全是public,都只是加班積極點,愛裝13,我也是醉了;

三、 排錯的簡單作法就是先作減法再作加法,不用開根號,呵呵簡單吧clip_image029

四、 能用SQL一次作完的事情就用SQL作,像下圖這種,徹底能夠在語句裏邊過濾排序吧;

clip_image031

相關文章
相關標籤/搜索