JPA中的@Version

    创建数据库表的时候,一般都有一些公共字段,这些公共字段不同的公司有各自的要求,有时候我也不大关心这些公共字段,只注意特定的字段就好,因为只要ctrl+c、ctrl+v就好,当然新建PO的时候也只要extend一个类abstractModel就可以,毕竟公共字段都是需要加的。但是当创建好之后对数据库进行操作的时候,发现了一个字段Version,随着操作会变化,尽管这个英文不难,版本,能顾名思义,但还是很诧异,不知道这个有什么作用。于是看了一下PO继承的类abstractModel中有一个字段version上有注解@Version。

@Version注解

@Version  
private Long version

关于version有这样一个例子

例:假设当前数据的版本为1,余额为100
a. 操作员A此时将其读出(version=1),并从其账户余额中扣除$50(100-50)。
b. 在操作员A操作的过程中,操作员B也要读入此用户信息(version=1),并从其账户余额中扣除$20(100-20)。
c. 操作员A完成修改工作,将数据版本号加1(version=2),连同余额$50一并提交数据库更新,此时由于提交数据版本大于数据库记录的当前版本,数据被更新,数据库记录版本更新为2。
d. 操作员B完成操作,也将版本号加1(version=2)试图向数据库提交数据$80,但此时比对数据库记录版本时发现,操作员B提交的数据版本号为2,数据库记录当前版本也为2,不满足“提交版本必须大于记录当前版本才能执行更新”的乐观锁策略,因此,操作员B的操作被驳回。

原来是这样的,会自动更新version的值

UPDATE MYENTITY SET ..., VERSION = VERSION + 1 WHERE ((ID = ?) AND (VERSION = ?))

    如果WHERE子句不能匹配记录(因为相同的实体已经被另一个线程更新),那么持久性提供者将抛出OptimisticLockException。这将防止创建两个一样的实体类实例。

这里又引出一个概念,乐观锁和悲观锁问题。

乐观锁和悲观锁

    悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

    乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

 【小结】

    并发操作有很多,防治并发操作带来问题的方法也有多种,各种方法都有利弊,不同的场景应当采取不同的方法处理,其中使用@Version只是其一,我们应该灵活应用,取长补短,达到想要的效果。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值