三、乐观锁插件
乐观锁:总认为不会出现问题,无论何时都不上锁,出现问题,再次更新值测试。
悲观锁:总认为会出现问题,总是先上锁再操作。
乐观锁实现过程:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
使用步骤:
-
数据库增加version字段,默认值为1
-
实体类增加version属性
@Version//乐观锁注解 private Integer version;
-
注册组件
package com.jx.config; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @MapperScan("com.jx.mapper")//扫描mapper @Configuration//配置类 public class MyBatisPlusConfig { //注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor(){ return new OptimisticLockerInterceptor(); } }
-
测试
//单线程成功 @Test void testOptimisticLocker1(){ User user = userMapper.selectById(2l); user.setName("更新姓名1"); userMapper.updateById(user); }
Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ee47d9e] was not registered for synchronization because synchronization is not active JDBC Connection [HikariProxyConnection@797526745 wrapping com.mysql.cj.jdbc.ConnectionImpl@5afbd567] will not be managed by Spring ==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=? ==> Parameters: 2(Long) <== Columns: id, name, age, email, create_time, update_time, version <== Row: 2, Jack, 20, test2@baomidou.com, null, null, 1 <== Total: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ee47d9e] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@748f93bb] was not registered for synchronization because synchronization is not active 2021-08-01 13:04:42.856 INFO 3340 --- [ main] com.jx.handler.UserHandler : start update fill .... JDBC Connection [HikariProxyConnection@1811587238 wrapping com.mysql.cj.jdbc.ConnectionImpl@5afbd567] will not be managed by Spring ==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=? ==> Parameters: 更新姓名1(String), 20(Integer), test2@baomidou.com(String), 2021-08-01 13:04:42.856(Timestamp), 2(Integer), 2(Long), 1(Integer) <== Updates: 1
//多线程失败 @Test void testOptimisticLocker2(){ User user1 = userMapper.selectById(2l); user1.setName("更新姓名1"); //模拟多线程插队 User user2 = userMapper.selectById(2l); user2.setName("更新姓名2"); userMapper.updateById(user2);//插队成功更新version值 userMapper.updateById(user1);//version值不匹配,update失败 }
JDBC Connection [HikariProxyConnection@1864074564 wrapping com.mysql.cj.jdbc.ConnectionImpl@7978e022] will not be managed by Spring ==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=? ==> Parameters: 更新姓名2(String), 20(Integer), test2@baomidou.com(String), 2021-08-01 13:16:32.283(Timestamp), 4(Integer), 2(Long), 3(Integer) <== Updates: 1 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2a43e0ac] Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@365cdacf] was not registered for synchronization because synchronization is not active 2021-08-01 13:16:32.300 INFO 18704 --- [ main] com.jx.handler.UserHandler : start update fill .... JDBC Connection [HikariProxyConnection@809260538 wrapping com.mysql.cj.jdbc.ConnectionImpl@7978e022] will not be managed by Spring ==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=? ==> Parameters: 更新姓名1(String), 20(Integer), test2@baomidou.com(String), 2021-08-01 13:16:32.3(Timestamp), 4(Integer), 2(Long), 3(Integer) <== Updates: 0