超爱学习网
mybatisPlus
一级目录
基础使用
常用注解
构造器类型
条件类型
curd接口
插件扩展
面试题
参考手册
版本
二级目录
插件
分页插件
乐观锁插件
多租户插件
防全表更新与删除插件
动态表名插件
数据权限插件
数据变动记录插件
非法SQL拦截插件
扩展
逻辑删除
通用枚举
字段类型处理器
自动填充功能
sql注入器
执行sql分析打印
数据安全保护
多数据源
流式查询

「 乐观锁插件」概念和作用

MyBatis-Plus 乐观锁插件是一种基于数据版本号机制来防止更新冲突的解决方案。它在数据表中使用一个额外的版本号字段(通常是 version)。当进行更新操作时,乐观锁插件会检查这个版本号,只有当版本号与数据库中的一致时,才会执行更新,并将版本号加一。这种机制适用于冲突概率不高但对数据一致性要求较高的场景,能有效防止数据更新时的冲突和覆盖问题。

1. 配置乐观锁插件

// 在 MyBatis-Plus 配置类中添加乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    return new OptimisticLockerInterceptor();
}

2. 实体类中添加版本号字段

// 实体类User添加版本号字段
public class User {
    private Long id;
    private String name;
    @Version
    private Integer version;
    // 省略其他字段和方法
}

3. 更新操作使用乐观锁

// 更新操作,自动使用乐观锁
User user = userService.getById(1L);
user.setName("张三丰");
boolean success = userService.updateById(user);
// 若更新失败(版本号不匹配),success 为 false

4. 乐观锁冲突处理

// 更新时检测到乐观锁冲突的处理
User user = userService.getById(1L);
user.setName("张三丰");
if (!userService.updateById(user)) {
    // 重新获取数据并重试或者做其他冲突处理
}

5. 结合事务使用乐观锁

// 在事务中使用乐观锁进行更新操作
@Transactional
public void updateUser(Long id, String newName) {
    User user = userService.getById(id);
    user.setName(newName);
    if (!userService.updateById(user)) {
        throw new OptimisticLockingFailureException("更新失败,数据可能已被修改");
    }
}

6. 批量更新时使用乐观锁

// 批量更新用户信息,每个用户记录都应用乐观锁
List<User> users = userService.listByIds(userIds);
for (User user : users) {
    user.setSomeField(newValue);
    userService.updateById(user);
}

7. 乐观锁与查询操作

// 查询操作不受乐观锁影响
List<User> users = userService.list(new QueryWrapper<User>().lambda().eq(User::getName, "张三"));

8. 自定义版本号字段

// 在实体类中使用自定义的版本号字段
public class User {
    private Long id;
    private String name;
    @Version
    private Long customVersion;
    // 省略其他字段和方法
}

9. 乐观锁与删除操作

// 删除操作不受乐观锁影响
boolean success = userService.removeById(1L);

10. 多线程环境下的乐观锁应用

// 在多线程环境下使用乐观锁进行安全的数据更新
public void updateUserDataConcurrently(Long userId, String newName) {
    User user = userService.getById(userId);
    user.setName(newName);
    if (!userService.updateById(user)) {
        // 处理更新失败的情况,例如重试或记录日志
    }
}