MybatisPlus中的乐观锁与悲观锁

一件商品,成本价是 80 元,售价是 100 元。老板先是通知小李,说你去把商品价格增加 50 元。小
李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到 150 元,价格太
高,可能会影响销量。又通知小王,你把商品价格降低 30 元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格 100 元;小王
也在操作,取出的商品价格也是 100 元。小李将价格加了 50 元,并将 100+50=150 元存入了数据
库;小王将商品减了 30 元,并将 100-30=70 元存入了数据库。是的,如果没有锁,小李的操作就
完全被小王的覆盖了。
现在商品价格是 70 元,比成本价低 10 元。几分钟后,这个商品很快出售了 1 千多件商品,老板亏 1
万多。
上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过
了,则重新取出的被修改后的价格, 150 元,这样他会将 120 元存入数据库。
如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证
最终的价格是 120 元。
使用version控制
需要在配置类中设置乐观锁插件
@Configuration
@MapperScan("com.example.demos.mapper")
public class MybatisPlusConfig {
  @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
      MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
      //添加分页插件
      mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
      //添加乐观锁插件
      mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
      return mybatisPlusInterceptor;
  }
}
首先是实体类
@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version//用来标识乐观锁版本号字段
    private Integer version;
}

然后是mapper层

@Repository
public interface ProductMapper extends BaseMapper {
}

测试

//测试乐观锁
@Autowired
private ProductMapper productMapper;
@Test
public void testVersionUpdate(){
    //小李取数据
    Product productLi = productMapper.selectById(1L);//查询版本是0
    //小王取数据
    Product productWang = productMapper.selectById(1L);//查询版本是0
    //小李修改+50
    productLi.setPrice(productLi.getPrice()+50);
    int result1 = productMapper.updateById(productLi);
    System.out.println("小李修改的结果"+result1);
    //小王修改-30
    /*
    * 这个时候小李已经修改了,版本号会变成1,小王修改因为版本号不同无法修改,会修改失败(小王这个时候的版本号是0)
    * 失败result2会是0
    * */
    productWang.setPrice(productWang.getPrice()-30);
    int result2 = productMapper.updateById(productWang);
    if(result2==0){
        //修改失败,重新取得version并更新
        productWang = productMapper.selectById(1L);//这个时候查询的版本号是1
        productWang.setPrice(productWang.getPrice()-30);
        result2 = productMapper.updateById(productWang);
    }
    System.out.println("小王修改重试的结果"+result2);
    //老板看价格
    Product p3 = productMapper.selectById(1L);
    System.out.println("老板看价格:" + p3.getPrice());
}

你可能感兴趣的:(MybatisPlus,java,开发语言)