struts 框架使用,出现的事务控制问题,请高手做答

目前系统中对事务的控制放在了上层,即ACTION的初始化到调用结束,即一个ACTION一个事务,配合到页面上就是一个页面,一个请求,一个ACTION,一个事务,目前存在问题,当进行财务转帐时,其间经历三个画面,1,输入信息转出.2输入信息转入检查3.确认后转入,分别对应3个ACTION请求,我想将整个过程放到一个事务中,但是又不要破坏现有框架,望高手做答,拜谢!

将事务放在上层?
说明你们没有对系统深入分析,很多系统表面上是是界面之间的事务,实际上是业务逻辑层的事务,你需要将界面和数据模型、流程等区别开来,建议用UML重新做一下系统分析。

bang 兄
谢谢回复,但请说点有用的话,项目打办完了,不可能再做分析了,还望有解决经验的话,提示一下,你也在上海,应该明白很多项目小,不会去做详细分析的

不是我说无用话,是我也想知道这个问题的答案。


事务贯穿多个用户界面,很快就会导致数据库连接用尽,除非客户端就那么几个。
在第一个Action里面(或者说页面)不要开启事务,事务全部放到最后一个Action里面处理。处理的时候检查你需要处理的数据是否被别人修改过(在用户接触前几个画面的时候其他用户可能修改相应的数据),如果数据没有被动过,就执行事务,否则放弃(并告诉用户数据已经被别人修改,让用户重来)。
判断数据是否被改过,可在表格里面添加版本字段来解决。(每次修改数据的时候也要同时修改其版本)
这是很多项目当中经常用到的处理方法。日本项目里面叫这种处理为"排他制御"。
不知道我有没有跑题。

如果一定要把事务的控制放在上层,不考虑性能,也是可以实现的。
只要你取得数据库连接并开始事务以后,不要Commit或关闭而是要把它放到Session里面,以后处理的时候只用这个连接。最后的处理完成以后才Commit和关闭连接。用Hibernate也是一样的道理。
显然,这样一个数据库连接长时间被一个用户独占,对资源是很大的浪费。

首先十分感谢leema兄的回答,可是对于第一种解决,是否显的还是很粗燥呢,修改表结构是不可能的,表是日本定义好的,保存数据在最后一步执行SQL操作是不好,不合理的,假想,人员财务转帐,最后1个页面报错,所有操作放弃,转出也没实现,用户难道不会觉的莫名奇妙吗(他只想后退,修改转出信息),第二种解决SESSION不可能放这个的,原因大家都明白.

后来我结合STRUTS本身和一些资料,想了个解决方案,首先,做好封装的CONNECTION对象,在STRUTS的配置中,把几个页面对应到同一ACTIONFORM,再第一个页面处理的时候把CONNECTION对象放进ACTIONFORM去,剩下的页面对应的同一ACTIONFORM都能拿到CONNECTION对象,问题就好办了,其实我很苯的,不知道我的看法和观点大家如何看,欢迎意见

如果FORM的SCOPE范围不设为Session或Application,不同页面得到的FORM还是不同的对象(其里面的CONNECTION对象也不同),所以他们还是不能在一个事物范围里面执行。
如果FORM的SCOPE范围设为Session,也就是说把FORM放到Session里面了(这也是等于把CONNECTION对象放到Session里面了)。

我不太清楚你们具体的业务,涉及到多少表格和记录,分几次操作。
我上面提到的是“消极派他制御”。
当然还有“积极派他制御”。就是说在最后一个Action处理的时候若发现要操作的数据已经被他人修改过,就把用户已经输入的信息放到Session里面暂时保存,而不是放弃。然后再从数据库里面去一次最新数据,让用户对照修改,再提交。
一般情况下“消极派他制御”即可满足大部分需要,我以前参加过的项目都是用到了“消极制御”。“积极制御”相对来说稍微麻烦一点。

跨界面的事务在开发中是要尽量避免的,如果一定要采用跨界面的事务,我建议你们发一张QA票确认一下日方能不能接受这种方案,否则最后还是要改回来的。
其实,日本项目里面也经常会碰到日方提供的基本设计有误的情况,修改表结构也是常有的事。基本设计是很难的一项工作,不可能开始就能考虑到所有情况。

以上只凭我个人的经验和感觉所述,仅供参考。

我觉得楼主真的要考虑业务层和持久层的设计问题,把事务处理放到下层,为什么要做成跨Action的事务?当然你会觉得我在说废话了,但是
想想,一个设计得不合理的东西,然后又要在这个东西的基础上要求一些好的解决方案,不大好吧!
这就像一个内心就已经烂了的冬瓜,却要从冬瓜的外表上设计一些好的维护冬瓜不烂的设计方案,难呀!(我觉得banq不是在说废话)
本来leema 说的用开放锁的的机制,能很好的解决多用户并发性的问题,但不幸的是,数据表不可以修改,还有好像也不是楼主想要的功能,
楼主只要求是事务处理!
对于楼主的把conn放到ActionForm不是一种好的作法,因为破坏了
Struts框架, 是一种黏度过高的设计!
我的作法是: 读取数据的时候,你可以把它放到VO这个视图中,然后
在传到web 层时显示(这里没有开启事务),进行认证的时候要修改提交则开启事务(把事务放到DAO中),接着回滚和提交,最后导入数据库里面的时候
也是同样开启,接着回滚和提交(放到DAO中),这样不知到可不可以满足?

> 进行认证的时候要修改提交则开启事务(把事务放到DAO中),接着回滚和提交,最后导入数据库里面的时候也是同样开启,接着回滚和提交(放到DAO中)..

没有看明白。

> 进行认证的时候要修改提交则开启事务(把事务放到DAO中),接着回滚和提交,最后导入数据库里面的时候也是同样开启,接着回滚和提交(放到DAO中)..

没有看明白。

写错了,对不起,是 “回滚或提交”,把“和”改成“或”字!

还是没听懂,麻烦详细解释下,谢谢了

我先说说你的需求,也许是存在误解,财务转帐,应该是在数据库里面
的信息,你先去取出来(Action),然后发配到页面,接着就是对这个页面
的信息转入检查,无误后转入数据库!
就这种功能需求,楼主怎么会设计出跨Action的事务呢? 想想,如
果一个用户准备转帐,他读取数据了以后, 就什么操作也不作,这样事
务始终是开启的,如果用户一小时不操作(转入),那么事务开启一小时,如果用户一多,则开启N个事务和打开N个conn,所以建议楼主放弃那
种作法!
其实楼主应该请leema 吃顿饭,对种情况leema 苦苦挽救,真是用心良苦!
用户要转帐,先是填入帐额,假定填入的ActionForm是AcctionActionForm,然后定位Action, 假设这个Action名是:
loadAccountAction,接着调用业务逻辑,调用DAO这里注意了,只是调用DAO的Query(),事务不必打开,因此在业务逻辑中是不是有足够的帐额要转,然后发配到页面,确认要转帐的数目。
在最后转帐的时候,同样要调用DAO,注意这时Update()了,首先开启事
务,减去转帐人的帐额,接着增加转帐目标人的帐额,接着提交或回
滚.....
这样没什么不好,当然楼主考虑到出错时返回是要能修改的,其实也很容易作,一种方法时设置Jsp缓存,在出错的界面上有一个“返回”按钮,定向到上面提过的loadAccountAction,不过要注意之前的
AcctionActionForm的生命期要设为Session....所以用户点击“返回”按
钮时就能够显示原先填入的帐额.......
好了,不知我这么说是不是详细?
还有一点就是我对你的业务不大了解,或许你要介绍清楚你的业务....

>一种方法时设置Jsp缓存,在出错的界面上有一个“返回”按钮
改成:
一种方法时设置Jsp缓存,另一种是在出错的界面上有一个“返回”按钮