论坛首页 Java企业应用论坛

巧用数据库事务拦截器解决流程内外的事务一致性问题

浏览 2328 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-03-11  
在使用流程引擎,如JBPM开发应用的时候,经常会遇见以下情况,即在流程引擎中要嵌入很多的Event Handler或者Action Handler来处理业务相关的事务,这其中就包括了写业务数据表等。
我们知道,在JBPM对于Event Handler或者Action Handler的执行异常,设计了相应的Exception Handler来处理,这使得在对业务数据表操作时,出现异常,流程是可以对异常进行处理的。(关于流程与Event Handler和Action Handler的执行顺序及关系,可参考咖啡blog中关于jBPM的文章,这里不做复述)

但反之,如果对业务数据表操作时正常,而流程处理自己发生了异常时问题就出现了。比如:我们向一个业务表成功插入了一条业务数据,希望流程走向下一个节点,但流程执行异常,停留在了上一个节点中,两者状态出现了不一致。

对jBPM了解的细心看官可能要问,流程引擎的内部是自洽的系统,怎么会发生异常呢?但实际上,确实会的。这种情况发生在多人并行任务中,当多人同时(就那么恰好)认领一个任务时。由于jBPM使用Hiberante的数据库存储,所以sql语句执行实际是发生在session.close()的时候。这时候,外部Handler中的数据库事务已经完成提交,但流程内部可能因为乐观锁机制(jBPM使用Hibernate Version保障数据一致性),甚至是网络物理链路损坏这样的极端情况,而不能正常完成执行。

这里,我们要清楚的意识到,流程引擎的数据库操作和业务数据库操作是完全分离的,两者可能是不同的数据库(分布式部署),使用不用的数据库上下文(对于Hibernate就是不同的SessionFactory)。那么如何解决不同数据库间的数据事务同步呢?

目前咖啡想到的方法是,巧用数据库事务拦截器(可参考本人Blog http://linliangyi2007.iteye.com/blog/288153,当然你也可是使用Spring等众多开源框架自带的事务拦截机制),将数据库事务延伸至Biz层来。

STEP 1。 在业务层声明事务方法txMethodA();《----数据库事务拦截器在进入这个方法前启动业务数据库的事务
STEP 2. 在事务方法txMethodA()中调用jBPM的api进行流程处理,在流程中会调用HandlerA的方法。
STEP 3. HandlerA中会调用相应的外部业务数据处理txMethodB(); 《---- 这里通过数据库事务拦截器,将它和txMethodA的事务统一在一个事务上下文中。

异常情况1. 如果txMethodB()外部业务数据处理异常,则将异常抛给jBPM的HandlerA,HandlerA将异常报告流程引擎,流程引擎使用Exception Handler对流程进行异常处理。这种情况没有异议!

异常情况2. 如果txMethodB()外部业务数据处理正常,则HandlerA执行正常。但由于“事务拦截器”的作用,在HanlderA执行后,事务并不提交。此时,流程执行发生异常,该异常将抛给txMethodA(),txMethodA()捕获流程异常后,在退出方法后,由“数据库事务拦截器”来负责对txMethodB()中事务的回滚。这样就保证了流程异常与业务处理状态的一致性!

当然也许有人会说这个破坏了MVC原则,但目前咖啡找到的还算优雅的解决方式就是这种了,欢迎拍砖,并提出更好的解决方案!!







 
   发表时间:2009-08-08  
能给个具体的实现?
0 请登录后投票
   发表时间:2009-08-08  
crabboy 写道
能给个具体的实现?


实现是有很多的,我们公司的企业资源管理平台就是这么做的,不过贴出来就显得太长了,周一去公司找找个短小精悍的例子,呵呵
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics