在数据库并发操作时,为了保证数据的正确性,我们会做一些并发处理,主要就是加锁。在加锁的选择上,有几种方式,悲观锁,乐观锁。
-
悲观锁,简单的理解就是把需要的数据全部加锁,在事务提交之前,这些数据全部不可读取和修改。
-
乐观锁,使用对数据进行版本校验和比较,来对保证本次的更新时最新的,否则就失败。
悲观锁的做法:
select * from user where id=1 for update;
update user set name='abc' where id=1;
这样,id为1的这行记录,就被锁住,在事务提交之前,他不可被其他事务读取和修改。
乐观锁的做法:
select id,name,version from user where id=1;
假设本次查询version=1,在更新操作时,
update user set name='abc', version=version+1 where id=1 and version=1
这样,当其他事务在本次事务提交之前更新了,version就会+1,就不是刚才查询到的1,本次update 就不会被执行。
在JPA中,我们可以使用@Version
在某个字段上进行乐观锁控制。
-
如对象中有
version
属性,并使用了@version
,在更新数据时请带上version
数据和主键
,这样可直接利用save
方法进行更新,当然这限于全部属性更新,局部更新时请使用@modify
和@update
方法。 -
当乐观锁更新失败的时候,会抛出异常:
org.springframework.orm.ObjectOptimisticLockingFailureException
-
当使用mysql数据库且JPA主键策略为
@GeneratedValue(strategy = GenerationType.IDENTITY)
,全局更新未带version
数据时,更新操作会变为保存操作。