mybatis-plus实现数据库层面的乐观锁
一、介绍:
悲观锁(同步锁):如果别的线程正在访问某个数据,则使其他线程挂起,同步等待,影响系统吞吐量正如其名,具有强烈的独占和排他特性。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度。因此,在整个数据处理过程中,将数据处于锁定状态。假设功能并发量非常大,就需要使用synchronized来处理高并发下产生线程不安全问题, 会使其他线程进行挂起等待从而影响系统吞吐量
乐观锁:乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。乐观锁适用于读操作多的场景,这样可以提高程序的吞吐量。 假设功能产生并发几率极少,采用乐观锁版本机制对比, 如果有冲突 返回给用户错误的
二、mybatis-plus实现乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个 version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果 version 不对,就更新失败
1、数据库中添加版本号字段version(可自定义)
2、对应实体类中对应字段加上@Version注解‘
@Version
private Integer version;
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1
newVersion
会回写到entity
中- 仅支持
updateById(id)
与update(entity, wrapper)
方法 - 在
update(entity, wrapper)
方法下,wrapper
不能复用!!!
3、添加乐观锁插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//导入乐观锁插件,和分页插件等一样,只需要一个bean,然后addInnerInterceptor即可
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
4、测试
//测试乐观锁
@Test
void testCAS(){
//假设线程1 age:
Employee employee1=employeeService.getById(1);
//假设线程2 age:
Employee employee2=employeeService.getById(1);
employee1.setAge(100);
employee2.setAge(80);
System.out.println(employeeService.updateById(employee1));
System.out.println(employeeService.updateById(employee2));
}