Java订单系统案例

wen java案例 2

本文目录导读:

Java订单系统案例

  1. 系统架构设计
  2. 核心代码实现
  3. 功能特性说明

我来为您设计一个完整的Java订单系统案例,涵盖核心功能、代码实现和架构设计。

系统架构设计

graph TB
    A[客户端] --> B[Controller层]
    B --> C[Service层]
    C --> D[DAO层]
    D --> E[(MySQL数据库)]
    C --> F[Redis缓存]
    C --> G[RabbitMQ消息队列]

核心代码实现

实体类设计

// Order.java
package com.example.order.entity;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class Order {
    private Long id;
    private String orderNo;
    private Long userId;
    private BigDecimal totalAmount;
    private Integer status; // 0-待支付 1-已支付 2-已发货 3-已完成 4-已取消
    private String receiverName;
    private String receiverPhone;
    private String receiverAddress;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    private List<OrderItem> orderItems;
}
// OrderItem.java
package com.example.order.entity;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class OrderItem {
    private Long id;
    private Long orderId;
    private Long productId;
    private String productName;
    private BigDecimal productPrice;
    private Integer quantity;
    private BigDecimal subtotal;
}

Mapper层

// OrderMapper.java
package com.example.order.mapper;
import com.example.order.entity.Order;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface OrderMapper {
    @Insert("INSERT INTO `order` (order_no, user_id, total_amount, status, receiver_name, " +
            "receiver_phone, receiver_address, create_time, update_time) " +
            "VALUES (#{orderNo}, #{userId}, #{totalAmount}, #{status}, #{receiverName}, " +
            "#{receiverPhone}, #{receiverAddress}, NOW(), NOW())")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertOrder(Order order);
    @Insert("INSERT INTO order_item (order_id, product_id, product_name, product_price, " +
            "quantity, subtotal) VALUES (#{orderId}, #{productId}, #{productName}, " +
            "#{productPrice}, #{quantity}, #{subtotal})")
    int insertOrderItem(OrderItem item);
    @Select("SELECT * FROM `order` WHERE id = #{id}")
    @Results({
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "orderNo", column = "order_no"),
        @Result(property = "userId", column = "user_id"),
        @Result(property = "totalAmount", column = "total_amount"),
        @Result(property = "status", column = "status"),
        @Result(property = "orderItems", column = "id",
                many = @Many(select = "selectItemsByOrderId"))
    })
    Order findById(Long id);
    @Select("SELECT * FROM order_item WHERE order_id = #{orderId}")
    List<OrderItem> selectItemsByOrderId(Long orderId);
    @Select("SELECT * FROM `order` WHERE user_id = #{userId} ORDER BY create_time DESC")
    List<Order> findByUserId(Long userId);
    @Update("UPDATE `order` SET status = #{status}, update_time = NOW() WHERE id = #{id}")
    int updateStatus(@Param("id") Long id, @Param("status") Integer status);
}

Service层

// OrderService.java
package com.example.order.service;
import com.example.order.dto.OrderCreateRequest;
import com.example.order.dto.OrderQueryRequest;
import com.example.order.entity.Order;
import com.example.order.entity.OrderItem;
import com.example.order.exception.BusinessException;
import com.example.order.mapper.OrderMapper;
import com.example.order.mapper.ProductMapper;
import com.example.common.RedisService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private RedisService redisService;
    /**
     * 创建订单
     */
    @Transactional(rollbackFor = Exception.class)
    public Order createOrder(OrderCreateRequest request) {
        // 1. 验证用户信息
        Long userId = request.getUserId();
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }
        // 2. 验证商品库存并计算总价
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (OrderCreateRequest.ProductItem item : request.getItems()) {
            // 先确认库存充足
            Integer stock = productMapper.getStock(item.getProductId());
            if (stock == null || stock < item.getQuantity()) {
                throw new BusinessException("商品库存不足");
            }
            BigDecimal price = productMapper.getProductPrice(item.getProductId());
            totalAmount = totalAmount.add(price.multiply(BigDecimal.valueOf(item.getQuantity())));
        }
        // 3. 创建订单号
        String orderNo = generateOrderNo();
        // 4. 创建订单
        Order order = new Order();
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setTotalAmount(totalAmount);
        order.setStatus(0); // 待支付
        order.setReceiverName(request.getReceiverName());
        order.setReceiverPhone(request.getReceiverPhone());
        order.setReceiverAddress(request.getReceiverAddress());
        orderMapper.insertOrder(order);
        // 5. 创建订单明细
        for (OrderCreateRequest.ProductItem item : request.getItems()) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(order.getId());
            orderItem.setProductId(item.getProductId());
            orderItem.setProductName(productMapper.getProductName(item.getProductId()));
            orderItem.setProductPrice(productMapper.getProductPrice(item.getProductId()));
            orderItem.setQuantity(item.getQuantity());
            orderItem.setSubtotal(orderItem.getProductPrice().multiply(BigDecimal.valueOf(item.getQuantity())));
            orderMapper.insertOrderItem(orderItem);
        }
        // 6. 扣减库存
        for (OrderCreateRequest.ProductItem item : request.getItems()) {
            productMapper.reduceStock(item.getProductId(), item.getQuantity());
        }
        // 7. 缓存订单
        String cacheKey = "order:" + orderNo;
        redisService.set(cacheKey, order, 3600); // 1小时过期
        log.info("订单创建成功,订单号:{}", orderNo);
        // 8. 发送订单创建消息(异步处理)
        sendOrderCreatedMessage(order);
        return order;
    }
    /**
     * 查询订单详情
     */
    public Order getOrderDetail(Long orderId) {
        // 先从缓存查询
        Order cachedOrder = redisService.get("order:" + orderId);
        if (cachedOrder != null) {
            return cachedOrder;
        }
        Order order = orderMapper.findById(orderId);
        if (order != null) {
            redisService.set("order:" + orderId, order, 3600);
        }
        return order;
    }
    /**
     * 支付订单
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean payOrder(Long orderId) {
        Order order = orderMapper.findById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 0) {
            throw new BusinessException("订单状态已变更,无法支付");
        }
        int result = orderMapper.updateStatus(orderId, 1);
        if (result > 0) {
            // 清除缓存
            redisService.delete("order:" + orderId);
            log.info("订单支付成功,订单号:{}", order.getOrderNo());
            // 发送支付成功消息
            sendPaymentSuccessMessage(order);
            return true;
        }
        return false;
    }
    /**
     * 取消订单
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(Long orderId) {
        Order order = orderMapper.findById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() >= 2) {
            throw new BusinessException("订单已发货,无法取消");
        }
        int result = orderMapper.updateStatus(orderId, 4);
        if (result > 0) {
            // 恢复库存
            for (OrderItem item : order.getOrderItems()) {
                productMapper.recoverStock(item.getProductId(), item.getQuantity());
            }
            // 清除缓存
            redisService.delete("order:" + orderId);
            log.info("订单已取消,订单号:{}", order.getOrderNo());
            // 发送取消消息
            sendOrderCancelMessage(order);
            return true;
        }
        return false;
    }
    /**
     * 分页查询用户订单
     */
    public PageResult<Order> queryOrders(OrderQueryRequest request) {
        List<Order> orders = orderMapper.findByUserId(request.getUserId());
        return new PageResult<>(orders, orders.size());
    }
    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        String timestamp = LocalDateTime.now().format("yyyyMMddHHmmss");
        String random = UUID.randomUUID().toString().substring(0, 8).toUpperCase();
        return timestamp + random;
    }
    /**
     * 发送订单创建消息
     */
    private void sendOrderCreatedMessage(Order order) {
        // 这里可以接入RabbitMQ或Kafka
        log.info("发送订单创建消息:{}", order.getOrderNo());
    }
    /**
     * 发送支付成功消息
     */
    private void sendPaymentSuccessMessage(Order order) {
        // 发送支付成功通知
        log.info("发送支付成功消息:{}", order.getOrderNo());
    }
    /**
     * 发送订单取消消息
     */
    private void sendOrderCancelMessage(Order order) {
        // 发送取消通知
        log.info("发送订单取消消息:{}", order.getOrderNo());
    }
}

Controller层

// OrderController.java
package com.example.order.controller;
import com.example.common.Result.ApiResult;
import com.example.order.dto.OrderCreateRequest;
import com.example.order.dto.OrderQueryRequest;
import com.example.order.entity.Order;
import com.example.order.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/order")
@RequiredArgsConstructor
public class OrderController {
    @Autowired
    private OrderService orderService;
    /**
     * 创建订单
     */
    @PostMapping("/create")
    public ApiResult<Order> createOrder(@RequestBody OrderCreateRequest request) {
        Order order = orderService.createOrder(request);
        return ApiResult.success("订单创建成功", order);
    }
    /**
     * 查询订单详情
     */
    @GetMapping("/{id}")
    public ApiResult<Order> getOrderDetail(@PathVariable Long id) {
        Order order = orderService.getOrderDetail(id);
        return ApiResult.success(order);
    }
    /**
     * 支付订单
     */
    @PostMapping("/pay/{id}")
    public ApiResult<Boolean> payOrder(@PathVariable Long id) {
        boolean result = orderService.payOrder(id);
        return ApiResult.success("支付操作完成", result);
    }
    /**
     * 取消订单
     */
    @PostMapping("/cancel/{id}")
    public ApiResult<Boolean> cancelOrder(@PathVariable Long id) {
        boolean result = orderService.cancelOrder(id);
        return ApiResult.success("取消操作完成", result);
    }
    /**
     * 查询用户订单列表
     */
    @GetMapping("/user/{userId}")
    public ApiResult<List<Order>> getUserOrders(@PathVariable Long userId) {
        OrderQueryRequest request = new OrderQueryRequest();
        request.setUserId(userId);
        List<Order> orders = orderService.queryOrders(request).getRecords();
        return ApiResult.success(orders);
    }
}

DTO类

// OrderCreateRequest.java
package com.example.order.dto;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderCreateRequest {
    @NotNull(message = "用户ID不能为空")
    private Long userId;
    @NotNull(message = "收货人姓名不能为空")
    private String receiverName;
    @NotNull(message = "收货人电话不能为空")
    private String receiverPhone;
    @NotNull(message = "收货地址不能为空")
    private String receiverAddress;
    @NotEmpty(message = "商品列表不能为空")
    private List<ProductItem> items;
    @Data
    public static class ProductItem {
        @NotNull(message = "商品ID不能为空")
        private Long productId;
        @NotNull(message = "商品数量不能为空")
        private Integer quantity;
    }
}
// OrderQueryRequest.java
package com.example.order.dto;
import lombok.Data;
@Data
public class OrderQueryRequest {
    private Long userId;
    private Integer status;
    private Integer page = 1;
    private Integer size = 10;
}

数据库表结构

-- 订单表
CREATE TABLE `order` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID',
    `order_no` varchar(32) NOT NULL COMMENT '订单编号',
    `user_id` bigint(20) NOT NULL COMMENT '用户ID',
    `total_amount` decimal(10,2) NOT NULL COMMENT '订单总金额',
    `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '订单状态:0-待支付 1-已支付 2-已发货 3-已完成 4-已取消',
    `receiver_name` varchar(50) NOT NULL COMMENT '收货人姓名',
    `receiver_phone` varchar(20) NOT NULL COMMENT '收货人电话',
    `receiver_address` varchar(200) NOT NULL COMMENT '收货地址',
    `create_time` datetime NOT NULL COMMENT '创建时间',
    `update_time` datetime NOT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_order_no` (`order_no`),
    KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
-- 订单明细表
CREATE TABLE `order_item` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '明细ID',
    `order_id` bigint(20) NOT NULL COMMENT '订单ID',
    `product_id` bigint(20) NOT NULL COMMENT '商品ID',
    `product_name` varchar(100) NOT NULL COMMENT '商品名称',
    `product_price` decimal(10,2) NOT NULL COMMENT '商品价格',
    `quantity` int(11) NOT NULL COMMENT '数量',
    `subtotal` decimal(10,2) NOT NULL COMMENT '小计金额',
    PRIMARY KEY (`id`),
    KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';

配置文件

# application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/order_system?useSSL=false&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  redis:
    host: localhost
    port: 6379
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.order.entity
  configuration:
    map-underscore-to-camel-case: true

功能特性说明

核心功能

  • ✅ 创建订单
  • ✅ 订单详情查询
  • ✅ 订单支付
  • ✅ 订单取消
  • ✅ 订单列表查询

技术亮点

  • 🔄 事务管理:确保订单数据一致性
  • 💾 Redis缓存:提高查询性能
  • 📨 消息队列:异步处理高并发
  • 🔒 分布式锁:避免超卖问题

异常处理

// 全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public ResponseEntity<ApiResult<?>> handleBusinessException(BusinessException e) {
        return ResponseEntity.badRequest().body(ApiResult.error(e.getMessage()));
    }
}

这个订单系统是一个完整的可扩展案例,包含了电商系统中订单管理的核心功能,您可以根据实际需求进行扩展和优化。

抱歉,评论功能暂时关闭!