乐观锁的实现原理是对数据的查找和更改都在同一版本下,数据库表中需要有version属性来保存当前版本,以user表为例
加上mp的乐观锁插件
@Configuration
//扫描mapper接口所在包
@MapperScan("com.example.demo.mapper")
public class MyConfig {
//而3.3.4版本以后推荐使用以下配置
//将mybatisPlusInterceptor方法注册为Spring的IOC容器中的组件
@Bean
public MybatisPlusInterceptor OptimisticLockerInterceptor() {
//获取MybatisPlusInterceptor对象
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加内部拦截器(参数为创建一个OptimisticLockerInterceptor(乐观锁拦截器))
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//将mybatisPlusInterceptor进行返回
return mybatisPlusInterceptor;
}
}
user类,注意版本上需要加@Version注解
public class User {
//指定主键的方式 value对应数据库主键名,type对应如何生成
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private String email;
private Integer gender;
private Integer age;
@Version
private Integer version;
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", age=" + age +
'}';
}
}
观察表中id为7的数据,我们对age先后执行+2和-1操作,+2操作能成功执行,因为此时版本没有修改,+2操作执行完成,version会自动加1,所以在-1操作执行前会检查版本号是否和查询出来的一致,如果不一致则不会更新
/**
* 乐观锁演示
*/
@Test
public void testUpdate()
{
//a查询7号用户
User user1= userMapper.selectById(7);
//b查询7号用户
User user2 = userMapper.selectById(7);
//a对age加2
user1.setAge(user1.getAge()+2);
userMapper.updateById(user1);
//b对age减1
user2.setAge(user2.getAge()-1);
int res =userMapper.updateById(user2);
if(res==0)
{
System.out.println("b更新失败");
//发起重试
user2=userMapper.selectById(7);
user2.setAge(user2.getAge()-1);
userMapper.updateById(user2);
}
}
打印的sql语句and version=?是检查版本号是否一致
执行完成观察7号数据的age和version数据的变化