随着系统的运行我的工作我起草查询出现了这样一个bug:工作列表中的当前步骤与历史中的当前环节并不符合。如下

 

  找到我起草这一块的sql,如下:

LEFT JOIN T_BPM_PROCESS_TASK task  ON task.processExecutionId = Execution.id AND task.taskId= ( select max(taskId) from T_BPM_PROCESS_TASK task2 where task2.processExecutionId = Execution.id)

   左连接taskactivityName即为当前步骤。以上逻辑是基于taskId是按照某种规则向上增长的,先处理的环节的taskId肯定比后处理的taskId小,但通过这个例子,也已经发现taskId并不严格按照向上增长的规律变化。

找到创建新任务的入口(TaskServiceImpl

commandService.execute(new NewTaskCmd(parentTaskId))

  这是一个命令模式,进入NewTaskCmd,进入execute()方法,再进入DBSessionImplcreateNewTask()方法,然后是createTask(),在这个方法里有的生成方法

long dbid = EnvironmentImpl.getFromCurrent(DbidGenerator.class).getNextId();

  上面是反射的应用,进到DbidGenerator的方法getNextId(),这是一个被同步的方法,每次只能有一个调用进入。我们再依次进入核心的方法acquireDbidBlock(),然后又是一个命令模式,AcquireDbidBlockCmdexecute,下面我们可以看到

PropertyImpl property = (PropertyImpl) session.createCriteria(PropertyImpl.class)       .add(Restrictions.eq("key", PropertyImpl.NEXT_DBID_KEY))       .uniqueResult();

  我们打开jbpm_property,里面有一条数据,指定的是id的生成方法以及步长。

  打开jbpm.task.hbm.xml可以看到

<id name="dbid" column="DBID_">       <generator class="assigned" />     </id>

  通ibernategenerator属性的意义这篇文章,我们可以知道assigned的用法,即

assigned(程序设置)

让应用程序在save()之前为对象分配一个标示符,save前通过自定义的id生成器生成了id。

大家都知道activiti5jbpm5的区别和联系

Activiti5出自Tom之手,在DBID生成器的实现这块是一样的,下面是一篇对activiti5ID自定义生成器的解释:

2activiti5的默认主键策略分析:

1)每次需要主键的时候从act_ge_property表中的next.dbid中获取下一个主键值,但是主键增长步长是100,也就是说每次从这里获取下一个值的时候,上次是100,下次的值是200.

2)他们所有需要主键的表都从这个表中获取下一个值

3)但是他们针对性能做了一个取巧处理,就是每次步长100,将这个步长cache在本地用sychronize方法调用,也就是说一段时间内只需要在本地获取主键即可,不需要访问数据实时更新,一定程度的缓解了数据库调用压力

4)但是对于高并发来说,这个只能局部缓解,并发写入压力,还是有造成主键重复的概率

通过以上的解释,不难发现为什么jbpm4DBID会出现小的情况,这与主键重复的原理是相似的。

通过以上分析,我们将我起草的查询逻辑改为:

AND task.createTime = ( select max(createTime) from T_BPM_PROCESS_TASK task2 where task2.processExecutionId = Execution.id limit 1)