SpringBoot订单项目优化:ShoppingCart数据冗余解决方案咨询
实现可复用ShoppingCart的解决方案
1. 数据模型调整
- 重构
ShoppingCart实体:移除与订单绑定的字段(如orderId),仅保留cloudProduct(商品关联)、amount(商品单价)两个核心字段,并为这两个字段添加唯一约束,确保同一商品+同一单价仅存在一条ShoppingCart记录。 - 新增中间关联实体
OrderShoppingCart(或命名为OrderItem),用于关联订单与ShoppingCart,同时存储该订单中此购物项的quantity(购买数量)。该实体需包含order(订单关联)、shoppingCart(购物项关联)、quantity字段,并给order和shoppingCart添加联合唯一约束,避免同一订单重复关联同一购物项。
2. 业务逻辑改造
在订单创建的服务层代码中,修改购物项处理逻辑,核心是"查询复用优先,不存在则新建":
- 遍历订单中的所有待购商品(含指定单价):
- 根据
cloudProductId和amount查询ShoppingCart表,判断是否已存在符合条件的记录。 - 若存在,直接复用该
ShoppingCart;若不存在,新建并保存ShoppingCart记录。 - 将当前订单与该
ShoppingCart的关联关系(含购买数量)存入OrderShoppingCart表。
- 根据
示例代码片段:
@Transactional public Order createOrder(OrderCreateDTO dto) { Order order = new Order(); // 初始化订单基础字段(如用户、创建时间等) orderRepository.save(order); for (CartItemDTO item : dto.getCartItems()) { // 查询或创建ShoppingCart ShoppingCart cartItem = shoppingCartRepository.findByCloudProductIdAndAmount(item.getProductId(), item.getAmount()) .orElseGet(() -> { ShoppingCart newCart = new ShoppingCart(); newCart.setCloudProduct(cloudProductRepository.getById(item.getProductId())); newCart.setAmount(item.getAmount()); return shoppingCartRepository.save(newCart); }); // 建立订单与购物项的关联 OrderShoppingCart orderItem = new OrderShoppingCart(); orderItem.setOrder(order); orderItem.setShoppingCart(cartItem); orderItem.setQuantity(item.getQuantity()); orderShoppingCartRepository.save(orderItem); } return order; }
3. 并发安全处理
高并发场景下,需避免多个请求同时创建相同的ShoppingCart记录,可通过两种方式保障:
- 利用数据库唯一约束:当重复插入同一商品+单价的
ShoppingCart时,数据库会抛出唯一键冲突异常,此时在代码中捕获异常,重新查询已存在的记录即可。 - 使用行级锁:修改查询语句,添加
for update锁,确保同一时间只有一个请求能创建该记录:ShoppingCart cartItem = shoppingCartRepository.findByCloudProductIdAndAmountForUpdate(item.getProductId(), item.getAmount()) .orElseGet(() -> { // 新建逻辑同前 });
4. 关键注意事项
- 商品金额变动处理:若后续商品单价调整,必须新建
ShoppingCart记录,不能修改已有记录,确保历史订单关联的购物项金额与创建时一致,保证数据一致性。 - 历史数据迁移:若已有旧的
ShoppingCart数据,需批量合并相同商品+金额的记录,再将旧订单与购物项的关联关系迁移到OrderShoppingCart表(原记录的数量字段需同步迁移)。 - 查询逻辑适配:后续查询订单详情时,需通过
OrderShoppingCart关联ShoppingCart获取商品和金额信息,调整原有查询逻辑。
内容的提问来源于stack exchange,提问作者Dadinho2000
相关产品推荐
相关产品推荐

