本文目录导读:

我来为您设计一个完整的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()));
}
}
这个订单系统是一个完整的可扩展案例,包含了电商系统中订单管理的核心功能,您可以根据实际需求进行扩展和优化。