Mybatis-Plus使用乐观锁
时间:2022-07-22
本文章向大家介绍Mybatis-Plus使用乐观锁,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
乐观锁面向场景
一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。
现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1多万。。。
乐观锁与悲观锁
- 上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过了,则重新取出的被修改后的价格,150元,这样他会将120元存入数据库。
- 如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是120元。
接下来是基于SpringBoot+MP来完成乐观锁的搭配使用。
模拟冲突
数据库中增加商品表
CREATE TABLE product (
id BIGINT ( 20 ) NOT NULL COMMENT '主键ID',
name VARCHAR ( 30 ) NULL DEFAULT NULL COMMENT '商品名称',
price INT ( 11 ) DEFAULT 0 COMMENT '价格',
version INT ( 11 ) DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY ( id )
);
添加数据
INSERT INTO product (id, NAME, price) VALUES (1, '外星人笔记本', 100);
实体类
@Data
public class Product {
private Long id;
private String name;
private Integer price;
private Integer version;
}
Mapper接口类
@Repository
public interface ProductMapper extends BaseMapper<Product> {
}
测试,模拟的是开头讲到的场景
@SpringBootTest
public class ProductMapperTest {
@Autowired
private ProductMapper productMapper;
@Test
void testConcurrentUpdate() {
//1、小李
Product p1 = productMapper.selectById(1L);
System.out.println(p1.getPrice());
//2、小王
Product p2 = productMapper.selectById(1L);
System.out.println(p2.getPrice());
//3、小李将价格加了50元,存入了数据库
p1.setPrice(p1.getPrice() + 50);
productMapper.updateById(p1);
//4、小王将商品减了30元,存入了数据库
p2.setPrice(p2.getPrice() - 30);
int result = productMapper.updateById(p2);
if (result == 0) {//更新失败,重试
//重新获取数据
p2 = productMapper.selectById(1L);
//更新
p2.setPrice(p2.getPrice() - 30);
productMapper.updateById(p2);
}
//最后的结果
Product p3 = productMapper.selectById(1L);
System.out.println("最后的结果:" + p3.getPrice());
}
}
解决方案(乐观锁注入)
原理
数据库中添加version字段 取出记录时,获取当前version
SELECT id,`name`,price,`version` FROM product WHERE id=1
更新时,version + 1,如果where语句中的version版本不对,则更新失败
UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1
实现
实体类更新
对version字段添加@Version
注解
@Data
public class Product {
private Long id;
private String name;
private Integer price;
@Version
private Integer version;
}
进行一系列配置
创建包config
,创建配置类MybatisPlusConfig
注意:此时拥有了删除配置类,就可以将启动类中的 @MapperScan
扫描注解 移动到这边。
然后注入乐观锁的Bean组件
@Configuration
@MapperScan("com.xn2001.mapper")
public class MybatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
回到原来的测试中继续测试,将数据库70重新改为100,运行测试类。
- 腾讯叮当首次系统性展示AI能力 开放日展示实战型解决方案
- Execute 方法(Find 对象)
- 在容器中部署mysql与数据持久化
- silverlight如何在运行时用代码动态控制(或创建)动画
- 小程序深夜连发4大功能!你们要的直播来了!
- 机器学习在现实生活中到底有哪些应用?
- 千锋郑州告诉你未来十年Python市场前景如何
- 读书笔记:基于web的工作流引擎设计
- 地图知识-坐标网
- silverlight/xap如何接收参数?
- Silverlight中多个Xaml("场景"? or "窗口"? )之间的切换/调用/弹出/传参数问题小结
- Keepalived使用梳理
- mysql操作命令梳理(4)-中文乱码问题
- 今日头条李磊:机器写作与 AI 辅助创作
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- servlet/filter/listener/interceptor区别与联系
- Linux下文本的简单处理(awk和sed)
- Spring4定时器 cronTrigger和simpleTrigger实现方法
- Tomcat远程调试
- IDEA建立Spring MVC Hello World 详细入门教程
- 嗯,手搓一个TinyPng压缩图片的WebpackPlugin也SoEasy啦
- Spring源码解析——核心类介绍
- IO之Basic IO
- 静态方法中注入bean
- 高通量数据中批次效应的鉴定和处理(五)- 预测并校正可能存在的混杂因素
- JVM 学习笔记(一)
- JVM 学习笔记(二)
- JVM 学习笔记(三)
- 算法数据结构 | 图论基础算法——拓扑排序
- JVM 学习笔记(四)