1.乐观锁
主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。
乐观锁实现方式:
2.乐观锁实现步骤
1)实体类添加version字段
@Data
@Entity
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //auto_increment类型
@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.INSERT_UPDATE)
private Date updateTime;
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;
//乐观锁字段
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
}
2)元对象处理器接口添加version的insert默认值
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(MyMetaObjectHandler.class);
@Override
public void insertFill(MetaObject metaObject) {
LOGGER.info("start insert fill ....");
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("deleted", 0, metaObject);
//元对象处理器接口添加version的insert默认值
this.setFieldValByName("version", 1, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
LOGGER.info("start update fill ....");
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
特别说明:
3)在 MpConfig 中注册 Bean 注意:添加@EnableTransactionManagement注解。
@EnableTransactionManagement
@Configuration
@MapperScan("com.simoniu.mpdemo.mapper")
public class MpConfig {
//逻辑删除插件
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
// 乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
4)测试
//测试更新成功
@Test
public void testUpdate() {
Users u = usersMapper.selectById(1L);
u.setName("张无忌");
int result = usersMapper.updateById(u);
System.out.println("受影响的记录条数是:" + result);
}
测试后分析打印的sql语句,将version的数值进行了加1操作。
//测试更新失败
@Test
public void testUpdate() {
Users u = usersMapper.selectById(1L);
u.setName("张无忌");
//模拟取出数据后,数据库中version实际数据比取出的值大,即已被其它线程修改并更新了version
u.setVersion(u.getVersion() - 1);
int result = usersMapper.updateById(u);
System.out.println("受影响的记录条数是:" + result);
}
测试后分析打印的sql语句,并不报错,但是更新失败。
在mybatisplus 3.4.0版本之后,实现乐观锁插件的拦截器类发生了变化,具体改变如下:
//基于mybatisplus 3.4.0 的写法
@Bean
public MybatisPlusInterceptor optimisticLockerInnerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}