1.1 表结构(必加 version)
ALTER TABLE product ADD COLUMN version INT DEFAULT 1 NOT NULL COMMENT '乐观锁版本号';
加 唯一索引防止同一用户重复下单。
1.2 订单表加唯一索引
ALTER TABLE `order` ADD UNIQUE INDEX uk_user_product (user_id, product_id);
2. 实体类
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
@Data
public class Product {
private Long id;
private Integer stock; // 库存
@Version // MyBatis-Plus 乐观锁标识
private Integer version;
}
3. MyBatis-Plus 乐观锁配置
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4. 最终完整业务代码
@Service
public class OrderService {
@Autowired
private ProductMapper productMapper;
@Autowired
private OrderMapper orderMapper;
private static final int MAX_RETRY = 3;
@Transactional
public void realCreateOrder(Long userId, Long productId) {
int retryCount = 0;
boolean success = false;
while (retryCount < MAX_RETRY && !success) {
try {
// 1. 查询库存
Product product = productMapper.selectById(productId);
if (product.getStock() <= 0) {
throw new RuntimeException("已售罄");
}
// 2. 扣库存(乐观锁)
product.setStock(product.getStock() - 1);
int rows = productMapper.updateById(product);
if (rows == 0) {
retryCount++;
Thread.sleep(10);
continue;
}
// 3. 创建订单(唯一索引防重复)
Order order = new Order();
order.setUserId(userId);
order.setProductId(productId);
orderMapper.insert(order);
success = true;
} catch (DuplicateKeyException e) {
// 唯一索引冲突 → 重复下单
throw new RuntimeException("请勿重复提交订单");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("系统异常");
}
}
if (!success) {
throw new RuntimeException("当前人数过多,请稍后再试");
}
}
}
5.总结
- @Version → 自动拼接
version = ?条件 - 更新返回 0 行 → 并发冲突
- 重试机制 → 提高成功率
- 唯一索引 → 防重复下单
- 全程无 synchronized → 高并发、集群安全、性能强
&spm=1001.2101.3001.5002&articleId=160025479&d=1&t=3&u=68231fefc875470782e3a12ccd0304ed)
1208

被折叠的 条评论
为什么被折叠?



