当前位置: 首页 > news >正文

麻城建设网站浙江城乡建设局和住建局

麻城建设网站,浙江城乡建设局和住建局,网站更新维护,布吉公司做网站🎯 Version 注解是什么?Version 是 MyBatis-Plus 提供的乐观锁注解。它用于解决并发场景下的数据更新冲突问题。乐观锁 vs 悲观锁悲观锁:认为每次操作都会冲突,直接加锁(如 SELECT FOR UPDATE)乐观锁&#…

🎯 @Version 注解是什么?

@Version 是 MyBatis-Plus 提供的乐观锁注解。它用于解决并发场景下的数据更新冲突问题。

乐观锁 vs 悲观锁

  • 悲观锁:认为每次操作都会冲突,直接加锁(如 SELECT FOR UPDATE

  • 乐观锁:认为冲突很少发生,通过版本号机制解决冲突

🔧 工作原理

  1. 读取数据时获取当前版本号

  2. 更新数据时版本号 +1

  3. WHERE条件中包含旧版本号检查

  4. 如果版本号不匹配,更新失败

🛠️ 完整配置示例

1. 添加依赖

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.0</version>
</dependency>

2. 配置乐观锁插件

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 关键:添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

3. 实体类中使用 @Version

@Data
@TableName("user")
public class User {@TableId(type = IdType.ASSIGN_ID)private Long id;private String name;private Integer age;@Version@TableField("revision")private Integer revision;  // 版本号字段// 其他字段...
}

📋 示例场景

示例1:基本使用

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public void updateUser(Long userId, String newName) {// 1. 先查询获取当前数据和版本号User user = userMapper.selectById(userId);System.out.println("当前版本号: " + user.getRevision()); // 比如: 1// 2. 修改数据user.setName(newName);// 3. 更新操作(MP会自动处理版本号)int result = userMapper.updateById(user);if (result > 0) {System.out.println("更新成功,新版本号: " + user.getRevision()); // 现在: 2} else {throw new RuntimeException("更新失败,数据可能已被其他线程修改");}}
}

示例2:并发冲突模拟

@Test
public void testConcurrentUpdate() {// 线程1new Thread(() -> {User user1 = userMapper.selectById(1L);user1.setName("Thread1");userMapper.updateById(user1); // 成功,version+1}).start();// 线程2(稍晚一点执行)new Thread(() -> {try { Thread.sleep(100); } catch (InterruptedException e) {}User user2 = userMapper.selectById(1L);user2.setName("Thread2");int result = userMapper.updateById(user2); // 失败,返回0System.out.println("线程2更新结果: " + result); // 输出: 0}).start();
}

示例3:数据库表结构

CREATE TABLE user (id BIGINT PRIMARY KEY COMMENT '主键',name VARCHAR(50) COMMENT '姓名',age INT COMMENT '年龄',revision INT DEFAULT 0 COMMENT '版本号,乐观锁字段',created_time DATETIME COMMENT '创建时间',updated_time DATETIME COMMENT '更新时间'
);

🔍 生成的SQL语句

更新时MP会生成这样的SQL

UPDATE user 
SET name = '新名字', revision = revision + 1 
WHERE id = 1 AND revision = 1

💡 高级用法

1. 使用Wrapper时的版本控制

public void updateWithWrapper(Long userId, String newName) {User user = userMapper.selectById(userId);Integer oldVersion = user.getRevision();UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("id", userId).eq("revision", oldVersion)  // 重要:包含版本条件.set("name", newName).setSql("revision = revision + 1");  // 手动版本+1int result = userMapper.update(null, wrapper);
}

2. 批量更新处理

public void batchUpdate(List<Long> userIds, String newName) {List<User> users = userMapper.selectBatchIds(userIds);for (User user : users) {user.setName(newName);try {userMapper.updateById(user);} catch (Exception e) {log.warn("用户 {} 更新失败: {}", user.getId(), e.getMessage());// 可以重试或记录失败}}
}

3. 自定义异常处理

@Service
@Slf4j
public class UserService {@Retryable(value = OptimisticLockingFailureException.class, maxAttempts = 3)public void updateWithRetry(Long userId, String newName) {User user = userMapper.selectById(userId);user.setName(newName);int result = userMapper.updateById(user);if (result == 0) {throw new OptimisticLockingFailureException("数据已被修改,请重试");}}// 重试失败后的处理@Recoverpublic void recover(OptimisticLockingFailureException e, Long userId, String newName) {log.error("用户 {} 更新失败,经过3次重试仍失败: {}", userId, e.getMessage());// 发送通知或记录日志}
}

⚠️ 注意事项

1. 字段类型必须为数值类型

// 正确 ✅
@Version
private Integer revision;@Version
private Long version;// 错误 ❌
@Version
private String version;  // 不支持字符串类型

2. 初始值设置

// 插入数据时,版本号通常从1开始
User user = new User();
user.setName("张三");
// revision 会自动设为1(如果数据库默认值为0)
userMapper.insert(user);

3. 数据库默认值

建议在数据库中设置默认值:

ALTER TABLE user MODIFY revision INT DEFAULT 1;

4. 不支持的情况

// 这些操作不会触发乐观锁:
userMapper.update(null, updateWrapper);  // 如果wrapper中没有包含版本条件
userMapper.deleteById(id);              // 删除操作不触发乐观锁
自定义SQL更新                           // 需要手动处理版本号

🎯 实际应用场景

场景1:库存扣减

public boolean reduceStock(Long productId, Integer quantity) {Product product = productMapper.selectById(productId);if (product.getStock() < quantity) {throw new RuntimeException("库存不足");}product.setStock(product.getStock() - quantity);int result = productMapper.updateById(product);return result > 0;
}

场景2:账户余额更新

public boolean transfer(Long fromAccountId, Long toAccountId, BigDecimal amount) {Account fromAccount = accountMapper.selectById(fromAccountId);if (fromAccount.getBalance().compareTo(amount) < 0) {throw new RuntimeException("余额不足");}fromAccount.setBalance(fromAccount.getBalance().subtract(amount));int result = accountMapper.updateById(fromAccount);if (result > 0) {// 更新对方账户Account toAccount = accountMapper.selectById(toAccountId);toAccount.setBalance(toAccount.getBalance().add(amount));accountMapper.updateById(toAccount);}return result > 0;
}

📊 总结

@Version 的核心价值

  1. 解决并发冲突:防止数据覆盖

  2. 无锁性能高:不需要数据库锁,性能更好

  3. 使用简单:只需一个注解+插件配置

  4. 自动管理:MP自动处理版本号增减

使用口诀

  • 配置插件不能忘

  • 字段类型要数值

  • 使用updateById

  • 失败处理要跟上

这样就能很好地利用乐观锁来解决并发更新问题了!

http://www.dtcms.com/a/396259.html

相关文章:

  • 手机开发商东莞优化哪家好
  • LVS负载均衡技术全解析
  • OpenSpot 2.0.3 | 国内外音乐下载免费,需要特殊网络,搜索最好用繁体中文
  • 【ROS2】Beginner: Client libraries - parameters / ros2doctor / pluginlib
  • 中文域名网站有哪些免费网站建站塔山双喜
  • 基于JavaSwing的扫雷(含操作手册和设计文档)
  • 在电脑上哪里可以做网站wordpress 安装语言设置中文
  • 算法一刷 数组(上)
  • 德州哪里做网站做网站美工
  • 甘肃省第八建设集团公司网站Wordpress 搜索热词
  • 两个网站如何做端口映射郴州网站建设软件定制开发制作
  • 天津微网站建设智慧团建注册登录入口下载
  • 第十周SSRF漏洞
  • Pyside6 + QML - 信号与槽06 - 一个信号触发多个函数
  • html5旅游网站八大员报名入口官网
  • 海外建站平台创建网站主题在哪里
  • 太阳能电池红外异常检测+光伏巡检创新+低空经济方案
  • 建阳网站建设wzjseo苏州网站优化哪家好
  • 自动化抓取谷歌AI实战
  • seo网站优化培训多少价格部署一个网站要做哪些工作
  • 如何免费注册网站域名个人注册公司的详细步骤
  • 龙华区住房和建设局网站官网钱多网站
  • 0基础如何做网站手机主页网站推荐
  • git status突然显示很多文件改动
  • 微网站免费软件互联网服务公司有哪些
  • 做婚纱摄影网站wordpress怎样添加模板
  • 成都科技网站建设咨指数
  • 化妆品销售网站的源代码好的空间网站
  • 快速构建网站网站上内容列表怎么做
  • 网站备案注销申请表深圳网站建设有没有市场