浏览 1886 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-01-09
如果在映射时,定义了 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 的值是否正确了。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |