Mybatis学习笔记(十)

实战案例

简要描述:通过实际的业务场景案例,展示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的优化策略和最佳实践。

核心概念

  • 连接池优化:数据库连接池的优化配置
  • 缓存策略:多级缓存的使用
  • 读写分离:主从数据库的读写分离
  • 分库分表:大数据量下的分库分表策略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值