zoukankan      html  css  js  c++  java
  • SpringBoot整合MybatisPlus3.X之乐观锁(十三)

    主要适用场景

    意图:

    当要更新一条记录的时候,希望这条记录没有被别人更新

    乐观锁实现方式:

    • 取出记录时,获取当前version

    • 更新时,带上这个version

    • 执行更新时, set version = newVersion where version = oldVersion

    • 如果version不对,就更新失败

    乐观锁配置需要2步 记得两步

    1.插件配置

    spring xml:
    
    <bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
    spring boot:
    
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    2.注解实体字段 @Version 必须要!

    @Version
    private Integer version;

    特别说明:

    • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

    • 整数类型下 newVersion = oldVersion + 1

    • newVersion 会回写到 entity

    • 仅支持 updateById(id)update(entity, wrapper) 方法

    • update(entity, wrapper) 方法下, wrapper 不能复用!!!

    示例

    示例Java代码(参考代码)

    int id = 100;
    int version = 2;
    ​
    User u = new User();
    u.setId(id);
    u.setVersion(version);
    u.setXXX(xxx);
    ​
    if(userService.updateById(u)){
        System.out.println("Update successfully");
    }else{
        System.out.println("Update failed due to modified by others");
    }

    示例SQL原理

    update tbl_user set name = 'update',version = 3 where id = 100 and version = 2
    • pom.xml

      <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter</artifactId>
              </dependency>
              <dependency>
                  <groupId>com.baomidou</groupId>
                  <artifactId>mybatis-plus-boot-starter</artifactId>
                  <version>3.2.0</version>
              </dependency>
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
              </dependency>
              <!-- https://mvnrepository.com/artifact/p6spy/p6spy -->
              <dependency>
                  <groupId>p6spy</groupId>
                  <artifactId>p6spy</artifactId>
                  <version>3.8.0</version>
              </dependency>
              <dependency>
                  <groupId>com.h2database</groupId>
                  <artifactId>h2</artifactId>
                  <scope>runtime</scope>
              </dependency><dependency>
                  <groupId>com.alibaba</groupId>
                  <artifactId>fastjson</artifactId>
                  <version>1.2.49</version>
                  <scope>test</scope>
              </dependency>
              <!-- for testing -->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
          </dependencies>
    • 配置类

      @Configuration
      public class MybatisPlusOptLockerConfig {
      ​
          @Bean
          public OptimisticLockerInterceptor optimisticLockerInterceptor() {
              return new OptimisticLockerInterceptor();
          }
      }
    • 实体类

      @Data
      public class User {
      ​
          @TableId(value = "id", type = IdType.AUTO)
          private Long id;
          private String name;
          private Integer age;
          private String email;
          @Version
          private Integer version;
      }
    • Mapper

      public interface UserMapper extends BaseMapper<User> {
      ​
      }
    • 启动类

      @SpringBootApplication
      @MapperScan("com.mp.locker.mapper")  //不加在容器里面获取不了
      public class LockerApplication {
      ​
          public static void main(String[] args) {
              SpringApplication.run(LockerApplication.class, args);
          }
      ​
      }
    • application.yml

      spring:
        datasource:
          driver-class-name: com.p6spy.engine.spy.P6SpyDriver
          url: jdbc:p6spy:h2:tcp://192.168.180.115:19200/~/mem/test
          username: root
          password: test
    • 测试类

      @SpringBootTest
      class LockerApplicationTests {
      ​
          @Autowired(required = false)
          UserMapper userMapper;
      ​
          @Test
          public void testUpdateByIdSucc() {
              User user = new User();
              user.setAge(18);
              user.setEmail("test@baomidou.com");
              user.setName("optlocker");
              user.setVersion(1);
              userMapper.insert(user);
              Long id = user.getId();
              //INSERT INTO user ( name, version, email, age ) VALUES ( 'optlocker', 1, 'test@baomidou.com', 18 )
              User userUpdate = new User();
              userUpdate.setId(id);
              userUpdate.setAge(19);
              userUpdate.setVersion(1);
              //UPDATE user SET version=2, age=19 WHERE id=6 AND version=1
              Assert.assertEquals("Should update success", 1, userMapper.updateById(userUpdate));
              //6 optlocker   19  test@baomidou.com   2  值变成2
              Assert.assertEquals("Should version = version+1", 2, userUpdate.getVersion().intValue());
          }
      ​
          @Test
          public void testUpdateByIdFail() {
              User user = new User();
              user.setAge(18);
              user.setEmail("test@baomidou.com");
              user.setName("optlocker");
              user.setVersion(1);
              //INSERT INTO user ( name, version, email, age ) VALUES ( 'optlocker', 1, 'test@baomidou.com', 18 )
              userMapper.insert(user);
              Long id = user.getId();
      ​
              User userUpdate = new User();
              userUpdate.setId(id);
              userUpdate.setAge(19);
              userUpdate.setVersion(0);
              //UPDATE user SET version=1, age=19 WHERE id=7 AND version=0
              userMapper.updateById(userUpdate);
          }
      ​
          @Test
          public void testUpdateByIdSuccWithNoVersion() {
              User user = new User();
              user.setAge(18);
              user.setEmail("test@baomidou.com");
              user.setName("optlocker");
              user.setVersion(1);
              userMapper.insert(user);
              Long id = user.getId();
      ​
              User userUpdate = new User();
              userUpdate.setId(id);
              userUpdate.setAge(19);
              userUpdate.setVersion(null);
              Assert.assertEquals("Should update success as no version passed in", 1, userMapper.updateById(userUpdate));
              User updated = userMapper.selectById(id);
              Assert.assertEquals("Version not changed", 1, updated.getVersion().intValue());
              Assert.assertEquals("Age updated", 19, updated.getAge().intValue());
          }
      ​
          /**
           * 批量更新带乐观锁
           * <p>
           * update(et,ew) et:必须带上version的值才会触发乐观锁
           */
          @Test
          public void testUpdateByEntitySucc() {
              QueryWrapper<User> ew = new QueryWrapper<>();
              ew.eq("version", 1);
              int count = userMapper.selectCount(ew);
      ​
              User entity = new User();
              entity.setAge(28);
              entity.setVersion(1);
      ​
              Assert.assertEquals("updated records should be same", count, userMapper.update(entity, null));
              ew = new QueryWrapper<>();
              ew.eq("version", 1);
              Assert.assertEquals("No records found with version=1", 0, userMapper.selectCount(ew).intValue());
              ew = new QueryWrapper<>();
              ew.eq("version", 2);
              Assert.assertEquals("All records with version=1 should be updated to version=2", count, userMapper.selectCount(ew).intValue());
          }
      ​
      }
  • 相关阅读:
    个人技术博客(α)
    git常用命令合集
    软件工程实践2017第二次结对作业
    软件工程实践2017第一次结对作业
    软件工程实践2017第二次作业
    软件工程实践2017第一次作业
    学习总结
    约瑟夫
    今天是星期几
    斐波那契数列取石子游戏
  • 原文地址:https://www.cnblogs.com/dalianpai/p/11779488.html
Copyright © 2011-2022 走看看