意图:
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
取出记录时,获取当前version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
乐观锁配置需要2步 记得两步
spring xml: <bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/> spring boot: @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
@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()); } ? }
SpringBoot整合MybatisPlus3.X之乐观锁(十三)
原文:https://www.cnblogs.com/dalianpai/p/11779488.html