乐观锁和悲观锁

 

场景: 一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时 后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。此时,小李和小王同时操作商品后 台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元 存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。现在商品价格 是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1万多

 

分析: 上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过了,则重新取出的被修改后的价格,150元,这 样他会将120元存入数据库。如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是120元

 

模拟上面的场景,模拟冲突

 

具体操作如下:

 

第一步: 准备数据,在数据库创建商品表并添加如下数据

 

第二步: 创建实体类,例如在src/main/java/com.huanf.mybatisplus/poji目录下新建Product类,写入如下

 

第三步: 创建mapper接口,例如在src/main/java/com.huanf.mybatisplus/mapper目录下新建ProductMapper接口并写入如下

 

第四步: 在MyBatisPlusPluginsTest类写测试代码,例如添加如下,注意自动装配写在类的外面,测试写在类的里面

 

 

解决冲突 -- MyBatis-Plus提供的乐观锁插件

 

原理: 每一次查询或更新,会进行一次版本号查询 例如在数据库中添加version字段,然后取出记录时,获取当前version,更新时,version + 1,如果where语句中的version版本不对,则更新失败 简单说就是我们在操作数据时假设拿到的版本号是1,当我们想要提交数据时,版本号必须也为1才能成功提交数据,不然就提交失败

先确保你有一个字段是控制版本号的,然后你的实体类里面也是有这个成员变量,然后才能进行如下操作

 

具体操作如下:

 

第一步: 在实体类的控制版本号的字段添加@Version注解,例如

 

第二步: 在MyBatisPlusConfig类,注意该类是我们的配置类,添加插件配置。注意我们只需要关注下面的乐观锁插件,其它的代码是前面留下来的

 

第三步: 先去数据库把价格重新改为原价100,然后再去执行'【模拟上面的场景,模拟冲突】'里面写的zidingyi_testPage4方法

查询结果: 会发现此时老板查到的数据是150,也就是只有小李+50,没有小王-20,所以100+50=150

 

思考为什么小李没有-20成功: 小李先拿到价格的修改权,然后再小王拿到价格的修改权,他俩的版本号是一致的,但是小李先提交,小李提交之后价格的版本号就变了, 由于小王的版本号还是之前的,到小王提交时,版本号对不上,所以小王就没有更新成功。注意代码的执行顺序从上往下执行

使用乐观锁的结论: 虽然没有完成老板的要求,但是起码不会冲突导致老板亏本

 

解决冲突 -- 优化修改的流程

 

由于小王的操作没有执行成功,所以我们来解决一下

这里就直接把新的test测试写出来了,如下