[Mybatis-Plus笔记] MybatisPlus-06-乐观锁

一、乐观锁简述

乐观锁指,对于同一个数据,某一个事务正在进行时,不会阻止其它事务的操作,但在更新操作时会判断此前是否有其它事务进行了更新

换句话讲,如果当前事务读取的数据是过时的,那么此事务不被允许进行更新操作

实现乐观锁通常用一个 version 字段来表示当前数据的版本

如果更新时发现当前 version 不是最新的,则不进行更新

二、乐观锁的实现

1. 创建表

参考下面创建表的脚本:

DROP TABLE IF EXISTS `tbl_user`;
CREATE TABLE `tbl_user`  (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) COMMENT  '姓名',
  `age` int COMMENT  '年龄',
  `email` varchar(50) COMMENT  '邮箱',
	`version` int DEFAULT 1 COMMENT '乐观锁版本号',
  PRIMARY KEY (`id`)
)

2. 实体类

在 version 字段上注解 @Version 即可

@Data
@TableName("tbl_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    @Version
    private Integer version;
}

3. 配置乐观锁拦截器

乐观锁拦截器是 OptimisticLockerInnerInterceptor,将它添加到 MybatisPlusInterceptor 中

和配置分页查询拦截器是同样的操作

@Configuration
public class MybatisPlusConfig {
    @Bean
    MybatisPlusInterceptor mpInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

4. 效果查看

我们模拟两个事务的运作,对同一行数据读取两次,分别进行更新操作,查看效果

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    UserMapper userMapper;
    @Test
    void testOptimisticLock() {
        User user1 = userMapper.selectById(1);
        User user2 = userMapper.selectById(1);
        
        user1.setName("Alice");	// 第一个更新操作
        int ret1 = userMapper.updateById(user1);
        
        user2.setAge(18);		// 第二个更新操作
        int ret2 = userMapper.updateById(user2);
        
        System.out.println(ret1 + " " + ret2);
    }
}

第一个更新的日志:

==>  Preparing: UPDATE tbl_user SET name=?, age=?, email=?, version=? WHERE id=? AND version=?
==> Parameters: Harada Miu(String), 18(Integer), tsewh@mail.com(String), 2(Integer), 1(Long), 1(Integer)
<==    Updates: 1

第二个更新的日志:

==>  Preparing: UPDATE tbl_user SET name=?, age=?, email=?, version=? WHERE id=? AND version=?
==> Parameters: Harada Miu(String), 18(Integer), tsewh@mail.com(String), 2(Integer), 1(Long), 1(Integer)
<==    Updates: 0

可见更新时的 WHERE 语句中自动加入了对 version 的判断,如果数据库中的 version 值与当前 version 不相等,则不会更新

所以第一次更新成功了,并且自动更新了 version + 1,导致第二次更新失败

[注意]

  • 进行更新时会先将实例中的 version + 1 再做 UPDATE,即使更新失败依然有 version + 1 的操作,所以更新失败后依然继续进行更新,会不断抬高版本号,最终更新成功
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值