Home > Java > javaTutorial > body text

How to use MyBatisPlus+SpringBoot to implement optimistic locking function

WBOY
Release: 2023-05-11 20:46:11
forward
876 people have browsed it

    1. Scenario of inconsistent mall data

    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.

    2. Demonstrate this process

    1. Add a product table to the database

    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);
    Copy after login

    2. Create an entity class

    @Data
    public class Product {
        private Long id;
        private String name;
        private Integer price;
        private Integer version;
    }
    Copy after login

    3. Create a Mapper

    public interface ProductMapper extends BaseMapper<Product> {
        
    }
    Copy after login

    4. Test

    @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());
    	}
    }
    Copy after login

    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

    3. Optimistic locking scheme

    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
    Copy after login

    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
    Copy after login

    4. Optimistic lock implementation process

    1. Modify the entity class

    Add @Version annotation

    @Version
    private Integer version;
    Copy after login

    2. Add optimistic lock plug-in

    @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);
        }
    
    }
    Copy after login

    3. Optimization process

    (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());
    	}
    }
    Copy after login

    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!

    Related labels:
    source:yisu.com
    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
    Popular Tutorials
    More>
    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template