在數據庫並發操作時,為了保證數據的正確性,我們會做一些並發處理,主要就是加鎖。在加鎖的選擇上,有幾種方式,悲觀鎖,樂觀鎖。
-
悲觀鎖,簡單的理解就是把需要的數據全部加鎖,在事務提交之前,這些數據全部不可讀取和修改。
-
樂觀鎖,使用對數據進行版本校驗和比較,來對保證本次的更新時最新的,否則就失敗。
悲觀鎖的做法:
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
數據時,更新操作會變為保存操作。