jbpm4.3一个著名的bug https://jira.jboss.org/browse/JBPM-2856 即:主流程中包含子流程,当子流程结束后,子流程相关的数据不会删除;主流程结束时,这部分数据也不会被删除,影响的表有3个:JBPM4_EXECUTION,JBPM4_VARIABLE ,JBPM4_LOB,这三个表中,最让人忌讳的莫过于JBPM4_LOB表了,它保存着JBPM中的流程定义(少部分数据,毕竟没事也不会老改流程)以及流程运行过程中存储的变量信息,即使用setVariable来保存的java对象都将序列化保存到该表中,如果子流程多且业务大,这个表在这样的BUG下,一段时间就可以到几十G甚至更大,像我们的应用,每天有N多的流程启动,一般两个月这个表就能到达60~80G,给数据库维护带来的非常大的麻烦。
回到正题,因为jbpm4.4与jbpm4.3除有个位数的类换了包名,其余完全一样(最主要是数据库),所以直接升级到jbpm4.4,同时我们的代码侵入了StartActivity,EndActivity,以及TaskActivity 三个类的public void execute(ActivityExecution execution) {},其中因为StartActivity及TaskActivity不会删除数据,没出问题。在EndActivity侵入中,我们的业务代码会先执行个查询,再执行删除,这样在有子流程结束时,我们的业务代码执行的查询会导致hibernate执行flush操作,提交sql到数据库。业务代码执行完毕返回到jbpm中时,导致出错
2012-8-24 18:00:35 org.hibernate.event.def.DefaultDeleteEventListener deleteTransientEntity
信息: handling transient entity in delete processing
2012-8-21 18:29:39 org.hibernate.event.def.AbstractFlushingEventListener performExecutions
严重: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not delete: [org.jbpm.pvm.internal.model.ExecutionImpl#2620040]
很显然是因为业务代码的查询导致了hibernate的flush操作,并最终导致hibernate 出现数据库与session同步错误并最终流程异常。因为我们的业务代码执行的操作是查询出一个实体,再删除它。于是在这里修改为直接执行删除语句,这样就不会导致flush了。修改完毕,测试,成功!
以前一个小流程走完,在BPM4_EXECUTION,JBPM4_VARIABLE ,JBPM4_LOB将分别流下2,27,18 条数据(因为我们流程中保存的流程数据变量非常多),这些数据全都是没用的数据,现在修改后,跑完流程,3个表最终记录没有变化,流程结束就全部把对应流程相关的数据都删除完了。
做完这一步,接下来就只要把上面三个表中之前的脏数据删除一下就行了,先删除JBPM4_LOB,再删除JBPM4_VARIABLE,最后删除JBPM4_EXECUTION。
经过测试发现,流程如果人工不干预,还是线程问题,并最终导致事务不一致,流程失败。当然这与对jbpm4.4代码侵入,以及事务没隔离导致,最终只好将此事暂搁。