实战案例
简要描述:通过实际的业务场景案例,展示MyBatis-Plus在真实项目中的应用,包括完整的代码实现和最佳实践。
核心概念:
- 业务建模:将业务需求转换为数据模型
- 架构设计:合理的分层架构设计
- 性能优化:针对具体场景的性能优化
- 扩展性:考虑系统的可扩展性
用户管理系统
简要描述:一个完整的用户管理系统,包含用户注册、登录、权限管理、用户信息维护等功能。
核心概念:
- 用户实体设计:用户基本信息、角色权限
- 安全认证:密码加密、JWT令牌
- 权限控制:基于角色的权限控制
- 数据验证:用户输入数据的验证
实体类设计:
// 用户实体类
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("sys_user")
@ApiModel(value = "User对象", description = "用户表")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户ID")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@ApiModelProperty(value = "用户名")
@TableField("username")
@NotBlank(message = "用户名不能为空")
@Length(min = 3, max = 20, message = "用户名长度必须在3-20之间")
private String username;
@ApiModelProperty(value = "密码")
@TableField("password")
@NotBlank(message = "密码不能为空")
@JsonIgnore // 序列化时忽略密码字段
private String password;
@ApiModelProperty(value = "邮箱")
@TableField("email")
@Email(message = "邮箱格式不正确")
private String email;
@ApiModelProperty(value = "手机号")
@TableField("phone")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@ApiModelProperty(value = "真实姓名")
@TableField("real_name")
private String realName;
@ApiModelProperty(value = "头像URL")
@TableField("avatar")
private String avatar;
@ApiModelProperty(value = "用户状态:0-禁用,1-启用")
@TableField("status")
private Integer status;
@ApiModelProperty(value = "最后登录时间")
@TableField("last_login_time")
private LocalDateTime lastLoginTime;
@ApiModelProperty(value = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
@ApiModelProperty(value = "更新时间")
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@ApiModelProperty(value = "逻辑删除:0-未删除,1-已删除")
@TableLogic(value = "0", delval = "1")
private Boolean deleted;
@ApiModelProperty(value = "版本号")
@Version
private Integer version;
}
Service层实现:
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public Result<UserVO> register(UserRegisterRequest registerRequest) {
// 1. 参数校验
validateRegisterRequest(registerRequest);
// 2. 检查用户名是否已存在
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getUsername, registerRequest.getUsername())
.or()
.eq(User::getEmail, registerRequest.getEmail());
if (baseMapper.selectCount(wrapper) > 0) {
return Result.error("用户名或邮箱已存在");
}
// 3. 创建用户
User user = new User();
BeanUtils.copyProperties(registerRequest, user);
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
user.setStatus(1); // 默认启用
if (save(user)) {
UserVO userVO = convertToUserVO(user);
return Result.success(userVO);
}
return Result.error("注册失败");
}
@Override
public Result<LoginResponse> login(UserLoginRequest loginRequest) {
// 1. 查询用户信息
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getUsername, loginRequest.getUsername())
.eq(User::getStatus, 1);
User user = baseMapper.selectOne(wrapper);
if (user == null) {
return Result.error("用户不存在或已被禁用");
}
// 2. 验证密码
if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
return Result.error("密码错误");
}
// 3. 生成JWT令牌
String token = jwtTokenUtil.generateToken(user.getUsername());
// 4. 更新最后登录时间
user.setLastLoginTime(LocalDateTime.now());
updateById(user);
// 5. 构建登录响应
LoginResponse response = new LoginResponse();
response.setToken(token);
response.setUser(convertToUserVO(user));
return Result.success(response);
}
}
订单管理系统
简要描述:一个电商订单管理系统,包含订单创建、支付、发货、退款等完整的订单生命周期管理。
核心概念:
- 订单状态机:订单状态的流转管理
- 库存管理:商品库存的扣减和回滚
- 分布式事务:跨服务的事务一致性
- 订单分表:大数据量下的分表策略
订单实体设计:
// 订单主表
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_order")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@TableField("order_no")
private String orderNo; // 订单号
@TableField("user_id")
private Long userId; // 用户ID
@TableField("total_amount")
private BigDecimal totalAmount; // 订单总金额
@TableField("discount_amount")
private BigDecimal discountAmount; // 优惠金额
@TableField("actual_amount")
private BigDecimal actualAmount; // 实际支付金额
@TableField("status")
private Integer status; // 订单状态
@TableField("payment_method")
private Integer paymentMethod; // 支付方式
@TableField("payment_time")
private LocalDateTime paymentTime; // 支付时间
@TableField("delivery_time")
private LocalDateTime deliveryTime; // 发货时间
@TableField("receive_time")
private LocalDateTime receiveTime; // 收货时间
@TableField("remark")
private String remark; // 订单备注
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableLogic(value = "0", delval = "1")
private Boolean deleted;
@Version
private Integer version;
}
// 订单明细表
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_order_item")
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@TableField("order_id")
private Long orderId; // 订单ID
@TableField("product_id")
private Long productId; // 商品ID
@TableField("product_name")
private String productName; // 商品名称
@TableField("product_image")
private String productImage; // 商品图片
@TableField("unit_price")
private BigDecimal unitPrice; // 单价
@TableField("quantity")
private Integer quantity; // 数量
@TableField("total_price")
private BigDecimal totalPrice; // 小计
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
}
订单Service实现:
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private ProductService productService;
@Autowired
private InventoryService inventoryService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public Result<OrderVO> createOrder(CreateOrderRequest request) {
// 1. 参数校验
validateCreateOrderRequest(request);
// 2. 检查商品库存
List<OrderItemRequest> items = request.getItems();
for (OrderItemRequest item : items) {
if (!inventoryService.checkStock(item.getProductId(), item.getQuantity())) {
return Result.error("商品库存不足:" + item.getProductName());
}
}
// 3. 生成订单号
String orderNo = generateOrderNo();
// 4. 计算订单金额
BigDecimal totalAmount = calculateTotalAmount(items);
BigDecimal discountAmount = calculateDiscountAmount(request.getCouponId(), totalAmount);
BigDecimal actualAmount = totalAmount.subtract(discountAmount);
// 5. 创建订单主表
Order order = new Order();
order.setOrderNo(orderNo);
order.setUserId(request.getUserId());
order.setTotalAmount(totalAmount);
order.setDiscountAmount(discountAmount);
order.setActualAmount(actualAmount);
order.setStatus(OrderStatus.PENDING_PAYMENT.getCode());
order.setRemark(request.getRemark());
if (!save(order)) {
return Result.error("创建订单失败");
}
// 6. 创建订单明细
List<OrderItem> orderItems = items.stream()
.map(item -> {
OrderItem orderItem = new OrderItem();
orderItem.setOrderId(order.getId());
orderItem.setProductId(item.getProductId());
orderItem.setProductName(item.getProductName());
orderItem.setProductImage(item.getProductImage());
orderItem.setUnitPrice(item.getUnitPrice());
orderItem.setQuantity(item.getQuantity());
orderItem.setTotalPrice(item.getUnitPrice().multiply(new BigDecimal(item.getQuantity())));
return orderItem;
})
.collect(Collectors.toList());
orderItemMapper.batchInsert(orderItems);
// 7. 扣减库存(预扣减)
for (OrderItemRequest item : items) {
inventoryService.deductStock(item.getProductId(), item.getQuantity());
}
// 8. 设置订单超时(30分钟后自动取消)
setOrderTimeout(order.getId(), 30);
// 9. 返回订单信息
OrderVO orderVO = convertToOrderVO(order, orderItems);
return Result.success(orderVO);
}
@Override
public Result<Void> payOrder(PayOrderRequest request) {
// 1. 查询订单
Order order = getById(request.getOrderId());
if (order == null) {
return Result.error("订单不存在");
}
// 2. 检查订单状态
if (!OrderStatus.PENDING_PAYMENT.getCode().equals(order.getStatus())) {
return Result.error("订单状态不正确,无法支付");
}
// 3. 调用支付服务
PaymentResult paymentResult = paymentService.pay(request);
if (!paymentResult.isSuccess()) {
return Result.error("支付失败:" + paymentResult.getMessage());
}
// 4. 更新订单状态
order.setStatus(OrderStatus.PAID.getCode());
order.setPaymentMethod(request.getPaymentMethod());
order.setPaymentTime(LocalDateTime.now());
if (!updateById(order)) {
// 支付成功但订单状态更新失败,需要人工处理
log.error("订单支付成功但状态更新失败,订单ID:{}", order.getId());
return Result.error("订单状态更新失败");
}
// 5. 取消订单超时任务
cancelOrderTimeout(order.getId());
// 6. 发送支付成功消息
sendPaymentSuccessMessage(order);
return Result.success();
}
@Override
public Result<IPage<OrderVO>> findOrderPage(OrderPageRequest request) {
// 1. 构建查询条件
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(request.getUserId() != null, Order::getUserId, request.getUserId())
.eq(request.getStatus() != null, Order::getStatus, request.getStatus())
.like(StringUtils.isNotBlank(request.getOrderNo()), Order::getOrderNo, request.getOrderNo())
.between(request.getStartTime() != null && request.getEndTime() != null,
Order::getCreateTime, request.getStartTime(), request.getEndTime())
.orderByDesc(Order::getCreateTime);
// 2. 执行分页查询
Page<Order> page = new Page<>(request.getCurrent(), request.getSize());
IPage<Order> orderPage = page(page, wrapper);
// 3. 转换为VO
IPage<OrderVO> result = orderPage.convert(order -> {
// 查询订单明细
List<OrderItem> items = orderItemMapper.selectList(
new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderId, order.getId())
);
return convertToOrderVO(order, items);
});
return Result.success(result);
}
/**
* 生成订单号
*/
private String generateOrderNo() {
String prefix = "ORD";
String timestamp = String.valueOf(System.currentTimeMillis());
String random = String.valueOf((int) (Math.random() * 1000));
return prefix + timestamp + random;
}
/**
* 设置订单超时
*/
private void setOrderTimeout(Long orderId, int timeoutMinutes) {
String key = "order:timeout:" + orderId;
redisTemplate.opsForValue().set(key, orderId, Duration.ofMinutes(timeoutMinutes));
}
}
权限管理系统
简要描述:基于RBAC(Role-Based Access Control)模型的权限管理系统,支持用户、角色、权限的灵活配置。
核心概念:
- RBAC模型:用户-角色-权限的三层模型
- 权限控制:方法级别的权限控制
- 动态权限:运行时动态加载权限
- 权限缓存:提高权限检查性能
复杂查询场景
简要描述:展示MyBatis-Plus在复杂查询场景下的应用,包括多表关联、统计分析、动态查询等。
核心概念:
- 多表关联:复杂的表关联查询
- 动态查询:根据条件动态构建查询
- 统计分析:数据统计和分析查询
- 性能优化:复杂查询的性能优化
高并发场景优化
简要描述:在高并发场景下MyBatis-Plus的优化策略和最佳实践。
核心概念:
- 连接池优化:数据库连接池的优化配置
- 缓存策略:多级缓存的使用
- 读写分离:主从数据库的读写分离
- 分库分表:大数据量下的分库分表策略