MyBatis-Plus 学习笔记-乐观锁


乐观锁(Optimistic Locking)是一种在读取数据时不会加锁,而是在更新数据时检查数据是否被其他事务修改的机制。如果数据被修改,则更新失败;否则,更新成功。

  • 低并发场景:当系统中的并发量较低时,乐观锁可以有效减少锁的竞争,提高系统的性能。
  • 读多写少的场景:如果系统中读操作远多于写操作,使用乐观锁可以避免频繁的锁竞争,提高读操作的效率。
  • 数据更新频率低的场景:对于那些更新频率较低的数据,乐观锁可以减少锁的开销,提高系统的响应速度。
  • 业务逻辑允许重试的场景:如果业务逻辑允许在更新失败后进行重试,乐观锁是一个不错的选择。因为即使更新失败,也可以通过重试来完成操作。
  • 分布式系统中的数据一致性:在分布式系统中,乐观锁可以用来保证数据的一致性,尤其是在跨服务调用时,可以减少锁的竞争和死锁的风险。

MyBatis-Plus 提供了 OptimisticLockerInnerInterceptor 插件,使得在应用中实现乐观锁变得简单。

乐观锁的实现通常包括以下步骤:

  1. 读取记录时,获取当前的版本号(version)。
  2. 在更新记录时,将这个版本号一同传递。
  3. 执行更新操作时,设置 version = newVersion 的条件为 version = oldVersion。
  4. 如果版本号不匹配,则更新失败。

 配置乐观锁插件

1. 配置插件


/**
 * 配置Mybatis-Plus乐观锁插件
 * 乐观锁是一种在读取数据时不会加锁,只有在更新数据时才会检查数据是否被修改的机制
 * 如果数据未被修改,则直接更新;如果数据已被修改,则会抛出异常或进行其他处理
 * 这种方式可以提高系统的并发性能,但需要开发者自行处理数据冲突的情况
 */
@Configuration
public class MybatisPlusOptLockerConfig {

    /**
     * 创建并配置Mybatis-Plus拦截器
     * 拦截器用于在SQL执行过程中添加额外的功能或修改SQL
     * 在这里,我们添加了乐观锁内拦截器,以实现乐观锁的功能
     * 
     * @return 配置好的Mybatis-Plus拦截器实例
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        // 创建Mybatis-Plus拦截器实例
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加乐观锁内拦截器到拦截器链中
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 返回配置好的拦截器实例
        return interceptor;
    }
}

2. 在实体类字段上添加 @Version 注解 

@Data
@TableName("sys_user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    @Version
    private Integer version;
}

3.使用

  /**
   * 批量更新带乐观锁
   * <p>
   * update(et,ew) et:必须带上version的值才会触发乐观锁
   */
@Test
public void testUpdateByEntitySucc() {
    // 准备查询条件,查找所有版本号为1的用户记录
    QueryWrapper<User> ew = new QueryWrapper<>();
    ew.eq("version", 1);
    // 获取符合条件的记录数
    long count = userMapper.selectCount(ew);

    // 创建一个新的User对象,并设置更新后的年龄和版本号
    User entity = new User();
    entity.setAge(28);
    entity.setVersion(1);

    // 验证更新的记录数与原始符合条件的记录数相同
    Assertions.assertEquals(count, userMapper.update(entity, null));

    // 重新初始化查询条件,查找版本号为1的记录
    ew = new QueryWrapper<>();
    ew.eq("version", 1);
    // 版本号为1的记录应已全部更新,因此此时应找不到记录
    Assertions.assertEquals(0, userMapper.selectCount(ew).intValue());

    // 初始化查询条件,查找版本号为2的记录
    ew = new QueryWrapper<>();
    ew.eq("version", 2);
    // 所有版本号为1的记录应已更新为版本号2,验证更新结果
    Assertions.assertEquals(count, userMapper.selectCount(ew).intValue());
}

@Version注解可以查看MyBatis-Plus 学习笔记-注解配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕德猫宁丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值