关于hibernate 的 长事务的问题

         
frank
03-07-25 14 1396 1


Session session1 = sessionFactory.openSession();
Employee employeeFromSession2 =
(Employee) session2.load(Employee.class, new Integer(employeeId));
session1.flush();
session1.connection().commit();
session1.close();


(a*)。。。。。。。。。。。。。。。。。
String newEmail = "something@different.com";
。。。。。。。。。。。。。。。。。。。。。。。。
employeeFromSession2.setEmail(newEmail);
session2.flush();
session2.connection().commit();
session2.close();

在web application中,当a 用户运行到了以上代码(a*)处 返回页面供用户修改,此时另外一个用户b 修改了同一个emplyee的name! 并提交。然后用户a 修改了email提交,作完后我发现b用户的提交又被a用户里的name(其实已经是脏数据了)复写回去了,b等于什么也没做。这样显得及不合理,不知道各位有什么好的解决办法,hibernate 里好像有version的,但不知道如何用,请教各位大虾

1
robbin
2003-07-25 15:08

首先你的程序逻辑让我看不懂。我看不出来你的session1有任何用处。

其次,你是否想说的是,两个并发用户a和b,从数据库中load数据,此时a和b都拿到同样的数据。然后b先修改数据并且提交事务关闭session。此时a保持的还是原始的旧数据,然后a修改数据,之后提交数据库,这样把b用户修改的数据给覆盖掉了。

如果我理解你的意思是这样的话,我只能告诉你这根本不关Hibernate的事,任何ORM都无能为力,是数据库的事情,你要保证你想要的情况,必须修改数据库的隔离级别。

但是有一种情况,Hibernate不会修改数据库。假设a和b都load同样的数据,然后b修改数据提交数据库。此时数据库中是b修改后的新数据,a中是旧的数据,然后a用户在界面没有修改,之后a用户提交数据库。

在此种情况下,Hibernate会判断出a的数据没有被更新过,即使显式强制提交,Hibernate也不会向数据库发送sql,也就是说只要a的旧数据没有被修改过,并不会发生脏数据复写的问题。

我怀疑你想说的是后一种情况。

frank
2003-07-25 15:44

是这样的:一张表有两个字段 a b ,用户A 需要修改a 字段,用户B 需要修改b字段,那么 两个操作都需要先将字段抽出给用户看,然后用户在界面上作了修改,然后提交给服务器,更新数据库! 由于是同一张表 所以两个用户肯定用到的是同一个class的不同的实例,总是存在这样的可能用户A B 同时LOAD ! 然后显示给用户看,此时不可能保存事务,只有断开连接,然后再保存的时候,再连接 ,就有可能相互覆盖了,有什么好的解决方法?
我以前用过jbuilder 的dataexpress dataset它就可以监测出这种情况

shenli
2003-07-25 15:59

对象version或timestamp,好像hibernate的doc上就有

robbin
2003-07-25 16:14

你可以这样试试看,我没有试过,但觉得应该可以。

表的Mapping文件中a字段和b字段的映射,添加属性:


<property
name="propertyName"
column=
"column_name"
type=
"typename"
update=
"false"

/>


默认update属性是true,改成false以后,session.update(...)的时候,如果该字段对应的类属性没有修改,就不会出现在sql语句里面,应该就会解决你这个问题了。

http://hibernate.bluemars.net/hib_docs/reference/html/or-mapping.html#or-mapping-s1-7

3Go 1 2 3 下一页