`

项目中碰到的Hibernate事务处理问题小结

阅读更多

1.事务的隔离级别(请参考:http://epub.itpub.net/3/4.htm)
我们使用的隔离级别是Oracle的默认隔离级别:提交读(read committed),它允许不
可重复读和幻象读。
例子:A开启事务1, B开启事务2;事务1中先执行查询,获得1条数据。
事务2这时候update了这条数据,事务1再次查询获得这条数据,这条数据和之前查询出
的数据可能不同!

2.可能产生错误的做法
很多程序会这样做:先查询,校验数据,处理业务逻辑后,然后update数据
第一次查询和update过程中,如果有别的用户也update了这条数据,可能会造成实际上
的校验无效

3.hibernate的解决方法
hibernate使用版本号(version)解决重复update的问题
hibernate实际这样操作数据:假设表A,版本号初始化值是1
事务1:先查询表A,这时候hibernate会获得这个版本号1
事务2:后查询表A,也获得了版本号1,但是在事务1之前update了表A,这时候
hibernate自动把版本号更新为2
事务1这时候再update表A,会这样做:update A set ... where version=1
此时update不到任何数据,系统会抛出exception.

4.我们该怎么做
a) 完全通过hibernate来处理数据,校验数据,将获得hibernate的版本号服务
b) 数据校验不能在action层中做,因为action不会开启事务
c) 校验数据时必须使用hibernate的load等方法获得数据,而不能使用spring的
jdbctemplate写sql获得数据.
   这样获得数据,会脱离hibernate的版本控制管理,会造成实际上的校验失效
d) 某些特殊的情况(比如通讯程序),不使用hibernate,那么必须自己管理版本号来避
免类似问题

5.read-only事务
在我们系统中,find/query开始的方法设置为read-only事务,只对读有效。
read-only是serializable的子集,保证了同一事务中两次查询会获得一个结果

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics