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

本文探讨了在使用JBPM流程引擎时遇到的问题:业务数据处理与流程状态不一致的情况,尤其是在多人并行任务场景下。提出了通过数据库事务拦截器实现业务数据处理与流程状态的一致性方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用流程引擎,如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 [url]http://linliangyi2007.iteye.com/blog/288153[/url],当然你也可是使用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原则,但目前咖啡找到的还算优雅的解决方式就是这种了,欢迎拍砖,并提出更好的解决方案!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值