还是关于ejb并发的问题。我原先发的帖子可能没有说清楚问题

原先发的帖子:http://www.jdon.com/jive/thread.jsp?forum=16&thread=14273

有一帐户entitybean,里面包括帐号 userId和余额 account属性,由 e1 表示,在sessionbean中有两个方法f1(),f2() 由s1表示
f1()的业务逻辑为
f1(int id,int m){
e1=e1home.findbyprimakey(id);
e1.setAccount(m);
}

f2(int id,int m){
e1=e1home.findbyprimakey(id); //1
Thread.Sleep(10000); //其他更新操作 //2
if(el.account>m){ //3
e1.setAccount(account-m); //4
}
}
s1,e1都是容器管理事务。

假设account 最初为2000;
首先有一个servlet调用f2(1,1000),当1步骤完毕后进入2步骤(2步骤相当于在此执行其他逻辑处理).于此同时另一个线程的servlet调用f1(1,500),当完成此调用后,entitybean的account属性值(包括数据库内)应为500了。f2方法执行完2步骤后,进入3步骤,我希望e1.account>m为false(因为account被改变为500),但实际情况时e1.account>m为true(调试可看到此处account还为2000),因此就执行4步骤,从而当f2执行完毕后,account的值为1000。这显然是不对的。我原先认为entitybean可以自动同步数据库,但现在看来好像并不是这么回事。我想请问各位大侠,你们用ejb时如何处理这种业务了?

你在f1(), f2()中有没有Catch系统Exception?

参见:http://www.jdon.com/jive/thread.jsp?forum=16&thread=14273

我认为,本来你这段代码是按照你的想法实现的,但是你的测试手段干扰了它,Thread.Sleep(10000); 这样语句是用问题的。以下面方式调用看看:

Thread.Sleep(10000); //其他更新操作 //2
e1=e1home.findbyprimakey(id); //1
if(el.account>m){ //3

1和3应该在一起。

to banq:
>> Thread.Sleep(10000); //其他更新操作 //2
>> e1=e1home.findbyprimakey(id); //1
>> if(el.account>m){ //3

我认为是减少了错误的发生,但实际上当e1=e1home.findbyprimakey(id); // 后还是有可能被中断,此时另一个线程将改变e1。
另外
e1=e1home.findbyprimakey(id); //1
Thread.Sleep(10000); //其他更新操作 //2
if(el.account>m){ //3
这样做,中Thread.Sleep(10000);只是模拟当首先得到e1后,根据e1的情况进行其他的操作。

我认为这和sessionbean中隔离级别有观,但不知道sessionbean中隔离级别如何实现?如果直接用jdbc则可以实现上述逻辑的完全正确性。

还有to 廉价劳力 :
我认为这和Catch系统Exception并无关系,因为程序并没有抛出异常呀?

还是顶一把吧

别那么确定,如果Catch了不处理,是无法察觉的 你最好全贴代码

master ejb2 上面有这种情况的讨论

你如果用servlet,用单县城的servlet就没有问题了,没做完就等待作完执行就可以了

如果从ejb角度考虑的话,这是一个事物的隔离等级的问题。
你的问题是经典的交叉存取问题。
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE 可以解决你的问题
四个等级,自己研究一下吧

to ccmoon :
那我如何在ejb上用这些隔离级别了?
不会是在数据库内设置这些隔离级别吧?

是在Entity Bean上设置的

各位,你们用ejb时就没有这个问题,或许就没有发现entitybean还有这种问题.你们可以按照我程序的逻辑试一试.难到你们不觉得这是一个问题吗?

这种问题发生的概率不高的
而且要求不是很严格的情况下,这种情况可以忽略的
如果做银行方面的系统,这种情况一般就不能忽略了
你去看看master ejb 2把
解决方案也告诉你了,你自己去理解一下吧

对于隔离级的问题,ejb规范2.0的第10.5.9节做了描述。比如jboss支持4种隔离级别。你可以在你使用的容器的特定的描述文件中进行描述。比如在jboss的jboss.xml的commit-option标签中描述。

这种情况通常不会发生,因为象sql server 数据库默认的事务隔离级别是不允许读到未提交的数据,也就是当一个会话在对数据库中一个表作更新的同时,另一个会话如果想读这个表,数据库自动同步,也就是一直等待先前的会话事务结束。如果是oracle数据库因为采用了快照的概念,允许另一个会话读数据,但不允许同时更新,所以也不会发生这种错误