2015/4/20

周末回去想了下,hibernate、mybatis、jdbc,都行,最终定了用mybatis,谁叫它这么优雅,acvtiviti是依赖了mybatis的,就不用再引入包了;

看了配置文件,之前配置的是jpa,再配置mybatis,配置文件就显得臃肿,很乱了;用jpa吧,貌似也不赖;

再写一个Repository;

写SQL的时候用到了,知识点:

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

mysql查询最后一条记录,不能用orderby:

需求:要取a1的最后一条数据来关联,语句如下;

解决:不能在inner join里边用order by xxx limit 1;

折中解决:用时间来限制;a1.START_TIME_>a2.START_TIME_

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的实体,各种报错;

好麻烦,jpa要写实体,要写HQL,原来我都写好SQL了,还要转换为HQL,hibernate真麻烦;

慢慢拷贝表字段写实体,每个实体要继承原有的entity;

先写一个测试用例,跑通了再说,别连查询都查不了,就浪费时间了;贴一些主要的代码:

实体:

Repository:

测试用例:

可以哦:

那开始慢慢写实体吧,写好再改HQL;

写好了HQL,开始测试:

报错:

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

摸不着头脑,先精简语句,先调通上半部分的union再说;

还是一样;

问度娘;度娘说是HQL写错了,哪里错了,她也不说,真是的;

再次精简:

还是一样;

再次精简:

还是一样;

哥,多了个左括号;继续奋战;

再加SQL:

加参数,加排序,很顺利;

另一个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

貌似一样的啊;

折腾了好久,用Run As Server里边的tomcat就可以,但用maven插件的方式启动就报错;

为啥呢?

优化到此为止,告一段落。

疑问:

1、jpa的注解方式写DAO层可以用原生SQL吗?HQL是这样的:

2、activiti的表字段和属性名虽然不一样,但还是可以识别,不算折磨人,为什么不能一样呢?一样不是更好吗?所有地方都可以拷贝,不用拷贝了修改,保留下划线可以理解,要是怕字段过长的话,别定那么长的字段就可以了,至少要保持一致,一致之后很多自动化的事情就好办了,比如写代码生成器;

3、设计良好的数据库,即使再复杂的查询也应该是很好写,为何这里的待办查询这么恐怖?

总结:

1、 新入职,接手已有项目,就是这么坎坷,习惯就好;

2、 论测试的重要性,一个语句测多少遍才测通啊,写测试还是非常有必要的,负责任的提现,但之前公司的开发人员,工作1年就当技术主管,代码都没写几行就主管,真心无语,还有个工作1年就封为架构师,写个JavaBean属性全是public,都只是加班积极点,爱装13,我也是醉了;

3、 排错的简单做法就是先做减法再做加法,不用开根号,呵呵简单吧

4、 能用SQL一次做完的事情就用SQL做,像下图这种,完全可以在语句里边过滤排序吧;

工作流性能优化(敢问activiti有扩展性?)(3)的更多相关文章

  1. 工作流性能优化(敢问activiti有扩展性?)(2)

    2015/4/17 粗略看了activiti的sql的,在ativity engine包里边: 没什么头绪,先用excel记录数据量少的时候本机的性能情况:   不打印hibernate的sql:一刷 ...

  2. 工作流性能优化(敢问activiti有扩展性?)(1)

    工作流待办(首页待办列表),加载缓慢,activiti本机,看了代码又是全部数据加载到内存,然后代码过滤,我为什么又说又呢? 用VisualVM做性能测试:   之前同事给的解决方案: 1.把&quo ...

  3. C#大型电商项目优化(三)——扩展性与支付

    上一篇文章引来不少非议,笔者并非对EF有看法,而是针对不同的业务场景和框架背景,挑选不同的方案.每个方案都有其优势劣势,挑选最快速,最简单的方案,是笔者的初衷. 看评论也是学习的过程,然而有些只做评价 ...

  4. 深入NGINX:我们如何设计它的性能和扩展性

    为了更好地理解设计,你需要了解NGINX是如何工作的.NGINX之所以能在性能上如此优越,是由于其背后的设计.许多web服务器和应用服务器使用简单的线程的(threaded).或基于流程的 (proc ...

  5. Java并发编程:性能、扩展性和响应

    1.介绍 本文讨论的重点在于多线程应用程序的性能问题.我们会先给性能和扩展性下一个定义,然后再仔细学习一下Amdahl法则.下面的内容我们会考察一下如何用不同的技术方法来减少锁竞争,以及如何用代码来实 ...

  6. 【Java/Android性能优5】 Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/android-imagecache/ 主要介绍一个支持图片自动预取.支持多种缓存算法.支持二级缓存.支持数据保存和恢复的图片缓存的 ...

  7. 【Java/Android性能优 4】PreloadDataCache支持预取的数据缓存,使用简单,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/preloaddatacache/ 本文主要介绍一个支持自动向前或向后获取新数据的缓存的使用及功能.Android图片内存缓存可见I ...

  8. MySQL 复制 - 性能与扩展性的基石:概述及其原理

    原文:MySQL 复制 - 性能与扩展性的基石:概述及其原理 1. 复制概述 MySQL 内置的复制功能是构建基于 MySQL 的大规模.高性能应用的基础,复制解决的基本问题是让一台服务器的数据与其他 ...

  9. Zend server最大化应用程序的性能、扩展性和可用性

    如果我有8个小时去砍到一棵树,我会花6个小时磨斧子”——林肯(美国总统) 你可以知道? 世界页面访问量的峰值超过7000万每分钟. CloudFare公司服务器问题,导致785000站点崩溃一小时. ...

随机推荐

  1. Git error: unable to create file xxx: Filename too long

    一.问题描述 在使用 git 时,提示 error: unable to create file xxx: Filename too long error: unable to create file ...

  2. 采用DCT进行图像压缩

    一.实验目的:熟悉变换编码的图像压缩方法 二.实验内容:以所给图像为例,采用dct进行图像压缩编码,通过改变模板矩阵中非零元素的个数,得到不同缩编码图像, 根据公式 ,编写程序计算原图像和dct变换后 ...

  3. 22. Generate Parentheses (recursion algorithm)

    Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...

  4. UML——再回首

    概述     在画图的过程中,发现自己还是有好多不懂的地方,对于四大关系理解的不是特别透彻,所以画图的过程中总是"剪不断,理还乱!"再一次整理四大关系,再回首必然丰收~~~ 1.实 ...

  5. jquery 更新值。。vue 如何监听?

    size.val(5); // 改变值 //触发 input 事件 ie11 下不能用 size[0].dispatchEvent(new Event('input'));   有些浏览器 不支持.. ...

  6. 026 Remove Duplicates from Sorted Array 从排序数组中删除重复项

    给定一个有序数组,你需要原地删除其中的重复内容,使每个元素只出现一次,并返回新的长度.不要另外定义一个数组,您必须通过用 O(1) 额外内存原地修改输入的数组来做到这一点.示例:给定数组: nums ...

  7. android 缓存路径

    用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的.大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中.这样当该应用被卸载后,这些数据还保 ...

  8. 简单的dp(dp专题)

    题目链接:https://vjudge.net/contest/216347#problem/C   Alice gets two sequences A and B. A easy problem ...

  9. C# 枚举与switch用法

    using System; namespace Csharp { class Program { //枚举 public enum TimeOfDay { Morning=, Afternoon=, ...

  10. MySQL复制机制原理

    背景介绍 复制,就是对数据的完整拷贝,说到为什么要复制,首先能想到的是怕数据意外丢失,使得用户蒙受损失. 当完成了数据复制之后,会发现它的优势不止这一点,假如一台机器宕机了,可以启用备份在另一台机器的 ...