當涉及到企業應用程序時,正確地管理對數據庫的併發訪問是相當重要的。爲此,咱們可使用Java Persistence API提供的樂觀鎖定機制。它致使在同一時間對同一數據進行屢次更新不會相互干擾。爲了使用OptimisticLocking,咱們須要一個實體(Entity),其中包含一個帶有@Version註釋的屬性。在使用它時,每一個讀取數據的事務都持有version屬性的值。在事務想要進行更新以前,它將再次檢查version屬性。若是值在此期間發生了更改,則拋出ObjectOptimisticLockingFailureException。不然,事務提交update並遞增version的值。這種機制適用於讀操做比更新或刪除操做多得多的應用程序。java
@Entity
@Table(name = "user")
@Data
@OptimisticLocking
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@Column(name = "username", unique = true, nullable = true, length = 50)
private String username;
private String password;
@Version
private Integer version;
@PrePersist
public void prePersist() {
version = 0;
}
}
複製代碼
spring data jpa在上一篇文章已經作過一些講解了【快學springboot】7.使用Spring Boot Jpa。感興趣的朋友能夠看看。這裏定義了一個version字段,使用了Version註解標識。PrePersist這個註解表示在新增數據以前執行。spring
public interface UserRepo extends PagingAndSortingRepository<User, Integer>, JpaSpecificationExecutor<User> {
}
複製代碼
public class UserTest extends SpringbootApplicationTests {
}
複製代碼
SpringbootApplicationTests這個類是使用Spring initialize新建項目的時候自動生成的用來作單元測試的類。在UserTest上注入UserRepo,而且寫一個新增user的單測。數據庫
執行以後查看數據庫。springboot
該記錄已經被建立出來了。bash
執行後查看數據庫:併發
能夠看到version字段自增了1。app
新建一個方法,以下單元測試
這裏查詢了兩次id爲1的記錄,而後分別更新了這條記錄。根據前面的描述,這裏會拋出一個ObjectOptimisticLockingFailureException異常。啓動測試,結果以下:測試
這是符合預期的。看下數據庫的version,在這種狀況下,咱們的預期結果是version變爲2。spa
經過數據庫的值查看,測試都是符合預期的。
咱們把User實體的OptimisticLocking註解去掉,而後再次執行上面的方法。
這一次程序順利執行了,而後查看下數據庫的記錄:
預期應該是version會變爲3,而後username變爲happyjava-new2。
經過結果來看,這是符合預期的。
spring data jpa經過OptimisticLocking實現了樂觀鎖,該樂觀鎖不是經過數據庫自身去實現的,它是經過version字段(須要Version註解標識)去實現的。若是update的數據時候,發現數據庫的version大於等於當前的version,則會拋出ObjectOptimisticLockingFailureException,錯誤信息是
Row was updated or deleted by another transaction
複製代碼