Home >Java >javaTutorial >How to use MyBatisPlus+SpringBoot to implement optimistic locking function
If there is a product in the mall, the cost price is 80 yuan and the selling price is 100 yuan. The manager first informed Xiao Li that he should increase the price of the goods by 50 yuan. Xiao Li was playing games and was delayed for an hour. Exactly an hour later, the manager felt that the price of the product had increased to 150 yuan, which was too high and might affect sales. Also inform Xiao Wang that you will reduce the price of the product by 30 yuan.
At this time, Xiao Li and Xiao Wang operate the product backend system at the same time. When Xiao Li is operating, the system first takes out the product price of 100 yuan; Xiao Wang is also operating, and the product price taken out is also 100 yuan. Xiao Li added 50 yuan to the price and stored 100 50 = 150 yuan in the database; Xiao Wang reduced the product by 30 yuan and stored 100-30 = 70 yuan in the database. Yes, if there is no lock, Xiao Li's operation will be completely covered by Xiao Wang's.
The current product price is 70 yuan, which is 10 yuan lower than the cost price. A few minutes later, more than 1,000 items of this product were quickly sold, and the boss lost more than 10,000 yuan.
CREATE TABLE product ( id BIGINT(20) NOT NULL AUTO_INCREMENT 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; }
public interface ProductMapper extends BaseMapper<Product> { }
@RunWith(SpringRunner.class) @SpringBootTest public class ProductVersionTest { @Resource private ProductMapper productMapper; @Test public void testProductUpdate() { //1、小李 Product p1 = productMapper.selectById(1L); //2、小王 Product p2 = productMapper.selectById(1L); //3、小李将价格加了50元,存入了数据库 p1.setPrice(p1.getPrice() + 50); int result1 = productMapper.updateById(p1); System.out.println("小李修改结果:" + result1); //4、小王将商品减了30元,存入了数据库 p2.setPrice(p2.getPrice() - 30); int result2 = productMapper.updateById(p2); System.out.println("小王修改结果:" + result2); //最后的结果 Product p3 = productMapper.selectById(1L); System.out.println("最后的结果:" + p3.getPrice()); } }
The final output is 70 yuan, which is different from the 120 yuan expected by the manager, resulting in a loss. How to prevent such anomalies from happening? The solution is to use optimistic locking
Add the version field in the database: when fetching the record, get the current version
SELECT id,`name`,price,`version` FROM product WHERE id=1
When updating, version 1, if the version in the where statement is incorrect, then Update failed
UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1
Add @Version annotation
@Version private Integer version;
@Configuration //@MapperScan("com.koo.modules.*.dao") public class MybatisPlusConfig { /** * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除) */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); //实现乐观锁,保证数据的准确性 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> configuration.setUseDeprecatedExecutor(false); } }
(Judge whether the second data update is successful, if not, re-fetch the data for update)
@RunWith(SpringRunner.class) @SpringBootTest public class ProductVersionTest { @Resource private ProductMapper productMapper; @Test public void testProductUpdate() { //1、小李 Product p1 = productMapper.selectById(1L); //2、小王 Product p2 = productMapper.selectById(1L); //3、小李将价格加了50元,存入了数据库 p1.setPrice(p1.getPrice() + 50); int result1 = productMapper.updateById(p1); System.out.println("小李修改结果:" + result1); //4、小王将商品减了30元,存入了数据库 p2.setPrice(p2.getPrice() - 30); int result2 = productMapper.updateById(p2); System.out.println("小王修改结果:" + result2); if(result2 == 0){//更新失败,重试 System.out.println("小王重试"); //重新获取数据 p2 = productMapper.selectById(1L); //更新 p2.setPrice(p2.getPrice() - 30); productMapper.updateById(p2); } //最后的结果 Product p3 = productMapper.selectById(1L); System.out.println("最后的结果:" + p3.getPrice()); } }
The output result is 120, the data is correct
The above is the detailed content of How to use MyBatisPlus+SpringBoot to implement optimistic locking function. For more information, please follow other related articles on the PHP Chinese website!