官方說明文檔
樂觀鎖:樂觀鎖假設數據一般情況下不會造成衝突,所以在數據進行提交更新的時候,纔會正式對數據的衝突與否進行檢測,如果發現衝突了,則返回給用戶錯誤的信息,讓用戶決定如何去做。
樂觀鎖實現方式:
- 取出記錄時,獲取當前version
- 更新時,帶上這個version
- 執行更新時, set version = newVersion where version = oldVersion
- 如果version不對,就更新失敗
在數據庫中添加Version字段,並且默認值爲1
補充實體類,並添加註解:
添加mybatis配置:
@MapperScan("com.qi.mapper")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
測試:
並且數據庫中version更新爲2
模擬多線程操作數據庫:
//測試樂觀鎖
@Test
public void testOptimisticLocker(){
//查詢用戶信息
User user = userMapper.selectById(1);
//修改用戶信息
user.setName("zhangsan");
user.setEmail("[email protected]");
//模擬線程2進程插隊操作
User user1 = userMapper.selectById(1);
//修改用戶信息
user1.setName("zhangsan2222");
user1.setEmail("[email protected]");
//執行
userMapper.updateById(user1);
//使用自旋鎖嘗試多次提交
userMapper.updateById(user);//此時如果沒有樂觀鎖,就會覆蓋插隊線程的值
}
因爲user帶的version版本號爲2,而user1將版本號version更新爲2+1,所以導致user比對version失敗導致user更新失敗.
特別說明:
- 支持的數據類型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整數類型下
newVersion = oldVersion + 1
newVersion
會回寫到entity
中- 僅支持
updateById(id)
與update(entity, wrapper)
方法 - 在
update(entity, wrapper)
方法下,wrapper
不能複用!!!