需求分析

电商订单流转系统核心功能包括:用户下单、支付处理、库存扣减、物流跟踪和状态更新。涉及订单表、商品表、用户表、库存表等数据模型,需实现事务一致性。

数据库设计

-- 用户表
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `balance` decimal(10,2) DEFAULT '0.00',
  PRIMARY KEY (`id`)
);

-- 商品表
CREATE TABLE `product` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`)
);

-- 库存表
CREATE TABLE `inventory` (
  `product_id` bigint NOT NULL,
  `stock` int NOT NULL DEFAULT '0',
  PRIMARY KEY (`product_id`)
);

-- 订单表
CREATE TABLE `order` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` bigint NOT NULL,
  `total_amount` decimal(10,2) NOT NULL,
  `status` varchar(20) NOT NULL DEFAULT 'CREATED',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
);

-- 订单明细表
CREATE TABLE `order_item` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `order_id` bigint NOT NULL,
  `product_id` bigint NOT NULL,
  `quantity` int NOT NULL,
  `price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`)
);

Java 核心实现

使用 Spring Boot + MyBatis 框架实现:

// 订单服务层
@Service
@Transactional
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private InventoryMapper inventoryMapper;
    @Autowired
    private UserMapper userMapper;

    public OrderDTO createOrder(OrderCreateRequest request) {
        // 校验库存
        request.getItems().forEach(item -> {
            Inventory inventory = inventoryMapper.selectById(item.getProductId());
            if (inventory.getStock() < item.getQuantity()) {
                throw new BusinessException("库存不足");
            }
        });

        // 扣减库存
        request.getItems().forEach(item -> {
            inventoryMapper.deductStock(item.getProductId(), item.getQuantity());
        });

        // 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setTotalAmount(calculateTotal(request.getItems()));
        orderMapper.insert(order);

        // 创建订单明细
        request.getItems().forEach(item -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(order.getId());
            orderItem.setProductId(item.getProductId());
            orderItem.setQuantity(item.getQuantity());
            orderItem.setPrice(getProductPrice(item.getProductId()));
            orderItemMapper.insert(orderItem);
        });

        return convertToDTO(order);
    }

    public void payOrder(Long orderId) {
        Order order = orderMapper.selectById(orderId);
        User user = userMapper.selectById(order.getUserId());
        
        if (user.getBalance().compareTo(order.getTotalAmount()) < 0) {
            throw new BusinessException("余额不足");
        }
        
        userMapper.deductBalance(order.getUserId(), order.getTotalAmount());
        orderMapper.updateStatus(orderId, "PAID");
    }
}

状态机设计

订单状态流转建议采用状态模式:

public interface OrderState {
    void pay(Order order);
    void deliver(Order order);
    void receive(Order order);
}

public class CreatedState implements OrderState {
    public void pay(Order order) {
        // 支付逻辑
        order.setState(new PaidState());
    }
    // 其他方法实现...
}

事务处理要点

  1. 库存扣减与订单创建需在同一事务
  2. 支付操作需要保证余额扣减和订单状态更新的原子性
  3. 建议使用@Transactional注解管理事务边界

性能优化建议

  1. 库存扣减使用乐观锁:
UPDATE inventory SET stock = stock - #{quantity} 
WHERE product_id = #{productId} AND stock >= #{quantity}

  1. 订单查询分库分表策略
  2. 热点商品库存采用预扣减+异步同步机制

异常处理方案

  1. 库存不足时触发补偿事务
  2. 支付失败时回滚订单状态
  3. 分布式场景考虑引入Saga模式

扩展性设计

  1. 订单状态变更通过事件驱动架构通知其他系统
  2. 物流模块可单独微服务化
  3. 支付模块支持多支付渠道插件式扩展
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐