
mybatis-plus - 乐观锁的使用添加版本号更新插件BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());returninterceptor;}实体的乐观锁字段 version添加Version注解注意:数据库也需要添加 version 字段ALTERTABLEUSERADDVERSIONINTDEFAULT1;#int类型 乐观锁字段支持的数据类型只有: int, Integer, long, Long, Date, Timestamp, LocalDateTime仅支持updateById(entity)和update(entity, wrapper)前提entity ! null。VersionprivateIntegerversion;正常更新使用即可//演示乐观锁生效场景TestpublicvoidtestQuick7(){// 先查询, 在更新, 获取version数据// 同时查询两条, 但是 version 唯一, 最后更新的失败UseruseruserMapper.selectById(5);Useruser1userMapper.selectById(5);user.setAge(20);user1.setAge(30);userMapper.updateById(user);// 乐观锁生效,失败!userMapper.updateById(user1);}有个坑坑1 - 新增的时候 version 没值第一次更新直接失败如果新增没带、数据库没设置 default 1insert 之后 versionnull。第一次 updateById 时where 条件versionnull数据库判断null null不是 true更新行数 0直接报冲突。✅ 规范数据库字段version int default 1实体不用手动 set version新增 MP 不会处理 version靠数据库默认值。坑2 - 只判断 rows 0但是分不清 “数据不存在” 和 “版本冲突”introwsmapper.updateById(entity);if(rows0){thrownewRuntimeException(数据被别人修改请重试);}问题rows0有两种可能id 不存在id 存在但是 version 不匹配并发修改。上面代码会把这两种情况混在一起抛同一个异常前端提示会误导用户。✅ 业务优化更新前必须先selectById判断记录是否存在再执行更新rows0才判定为乐观锁冲突。Userusermapper.selectById(id);if(usernull){thrownewBusinessException(记录不存在);}// 修改字段introwsmapper.updateById(user);if(rows0){thrownewBusinessException(数据已被其他用户修改请刷新页面重试);}updateById(entity)✅ 最稳业务首选。最常用不容易踩坑。先查拿到version改字段updateById。update(entity, wrapper)✅ 能用但尽量少用。为什么少用where条件 主键(如果实体带id) wrapper条件 AND version?条件叠加容易写出意料之外的SQL。例子实体id1wrapper写eq(id,2)where就变成id1 AND id2 AND version?直接更新0行这种bug很难排查。很多新人踩这个坑实体带idwrapper又写id条件冲突。