hibernate在什么时候才会去检测持久化对象的version?

如果在映射时,定义了 optimistic-lock=”version”,同时映射了 <version name=”version” type=”integer” unsaved-value=”negative”/>,那么就会起用hibernate的乐观锁机制。hibernate会在执行update merge等更新操作时对比数据库里的该行的version和当前对象的version是否一样,如果一样则更新,不一样则出异常。但是 hibernate并不会在所有的更新操作时都做去对比这个version。

乐观锁是用来处理并发事务的。如果有多个事物同时对一行数据进行更新,那么才会检测这个version;反之,如果在一个事务内部,无论对 version做怎么样的更改,都不会检测。那么hibernate是如何做到这一步的呢?在每个事务提交的时候,hibernate会判断当前事务里有哪些对象被更新到数据库里,如果这个对象处理持久化状态,则不检查它的version,如果处于游离态,则要在更新前检查version。

换句话说,如果对象是在当前的事物里通过load方法,get方法,或者通过query等查询出来的,那么这个对象在当前事物里处于持久化状态,hibernate 就不会检测version。如果对象不是在当前事务中被从数据库中读出来的,而是程序新建,或者是前一个事务或前一个session里取出来的,那么在当前事务里它就处于游离态,hibernate就会检version。

例如,有一个类Person,需要更新属性name。于你查出这个对象把这个对象在页面显示,并且让用户在页面上更改完成并提交时,form里包含那个对象的id,要更新的字段name和version。这样当用户提交后,在后台,如果你是这样做的:

//……

Transaction transaction = session.beginTransaction();

Person person = (Person) session.load( Person.class, id);

person.setName(name);

person.setVersion(version);

session.update(person);

transaction.commit();

//……

上面那种情况,因为被update的person是从当前事务中查询出来的,正处于持久化状态,所以在更新时,就算页面传来的version值比前数据库里的version值小,hibernate也不会报错,因为它根本就不会检测。如果想让hibernate检测,你可以这样做:

//……

Transaction transaction = session.beginTransaction();

Person person = new Person();

person.setId(id);

person.setName(name);

person.setVersion(version);

session.update(person);

transaction.commit();

//……

由于是新建出来的person,这时的person处于游离态,所以在后面的更新时,hibernate就会按照你的意愿去检测version 了。

但是上面的方法还是有问题,就是如果那个Person里有很多个属性,而你只要改其中一部分,如果你不把所有的属性都扔到页面上,再在回来时写入新建的person里,那么在更新时,很可能会就会把一些你不想被更新字段给覆盖掉。而且,如果person和其它对象有外键关联,就更麻烦了。在这样的情况下,还是从数据库里取出当前对象,并更新它的那几个字段来得方便,不过这个时候如果你真的需要检测version,估计只好手动判断version 的值是否正确了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值