赞
踩
参考自:乐观锁插件
意图:
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
还是使用之前的user表,在user表中新增一个字段"version",类型为int,默认值为"1"。
修改实体类,给实体类增加上version属性,并且在该属性上增加@Version注解。
@Version注解描述:乐观锁注解、标记 @Verison 在字段上
@Data public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; /** 字段自动填充策略 */ @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.UPDATE) private Date updateTime; /** 乐观锁 */ @Version private int version; }
创建一个配置类MybatisPlusConfig(mybatis-plus的配置)。
然后进行乐观锁的插件配置。
/** * mybatis-plus 配置 * * 注解:@Configuration 代表这是一个配置类 * 注解:@EnableTransactionManagement 开启事务管理(默认就是开启的) * 注解:@MapperScan 代表扫描该包下的mapper接口(这样启动类就不需要加这个了) * @author ChangSheng * @date 2020-04-24 */ @Configuration @EnableTransactionManagement @MapperScan("com.slensoft.mp.samples.quickstart.mapper") public class MybatisPlusConfig { /** 乐观锁插件配置 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor(){ return new OptimisticLockerInterceptor(); } }
注意:id为"1"的用户,他的version如果为"null",需要手动给他填写1。
在单线程下会一直是成功的。如下测试代码
/** 乐观锁测试成功(单线程) */
@Test
public void testLock01() {
// 1.查询用户
User user = userMapper.selectById(1L);
// 2.修改
user.setName("testLock01");
// 3.执行
userMapper.updateById(user);
}
模拟多线程环境。
“模拟线程1”在操作时,“模拟线程2”插队进行了操作,此时如果没有乐观锁,那么最后一句更新操作将覆盖掉“模拟线程2”的操作。
此时每次运行如下代码,会发现version每次都会自增1。
/** 乐观锁测试失败(多线程) */
@Test
public void testLock02() {
// 模拟线程1操作
User user = userMapper.selectById(1L);
user.setName("testLock02 - 111");
// 模拟线程2操作(模拟另一个用户,他插队了线程1的操作)
User user2 = userMapper.selectById(1L);
user2.setName("testLock02 - 222");
userMapper.updateById(user2);
// 如果没有乐观锁,下面语句将会覆盖“模拟线程2”的操作。有乐观锁则不会。
userMapper.updateById(user);
}
所以,多线程环境下,一定要加锁。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。