ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot3 + MyBatisPlus 实战全套踩坑总结(分页、多表、事务、库存、VO规范)

SpringBoot3 + MyBatisPlus 实战全套踩坑总结(分页、多表、事务、库存、VO规范) 最近从零搭建SpringBoot3 MyBatisPlus3.5.9后端项目完成商品、订单、库存整套业务开发过程中踩遍了新手高频坑分页插件失效、IPage与Page区别、多表联查映射异常、VO/DTO规范、订单事务回滚、库存超卖、时间生成、JSON传参问题等。本文把所有实战问题 标准答案 最优写法一次性总结适合新手收藏直接复用业务代码。一、MyBatisPlus3.5.9 分页插件报错问题1. 问题现象升级 SpringBoot3 配套 MP 版本3.5.9后代码爆红Cannot resolve symbol PaginationInnerInterceptor分页插件无法使用。2. 根本原因MP3.5.9 版本拆分了分页依赖不再内置在 starter 中SpringBoot2 JDK8需要引入mybatis-plus-jsqlparser-4.9SpringBoot3 JDK17需要引入标准mybatis-plus-jsqlparser3. 正确依赖!-- SpringBoot3 MP核心依赖 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.9/version /dependency !-- 3.5.9必须额外引入分页依赖 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-jsqlparser/artifactId version3.5.9/version /dependency4. 完整分页配置类Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }二、IPage 和 Page 核心区别90%新手混淆1. 核心关系IPage接口定义分页规范getRecords、getTotal、getCurrentPageIPage 的默认实现类可 new 实例2. 工程标准写法入参 new Page返回值用 IPage 接收面向接口编程// 构造分页参数 PageProductVO pageParam new Page(current, size); // 自定义多表分页查询 baseMapper.selectProductVOPage(pageParam, name, categoryId); // pageParam 会被自动填充数据无需接收返回值3. 关键结论MP 分页插件会自动填充你传入的 Page 对象传参和接收结果是同一个对象。三、VO 规范只返回前端需要的字段1. 核心原则Entity 对应数据库全字段VO 只保留前端展示字段实现数据脱敏隐藏删除标记、创建人等内部字段。2. 标准VO示例订单VOData public class OrderVO { private Long id; private String orderNo; private String customerName; private BigDecimal totalAmount; private Integer status; private LocalDateTime createTime; }四、多表联查分页最佳实践MP不支持多表Wrapper1. 核心知识点MyBatisPlus 的LambdaQueryWrapper 仅支持单表查询多表 JOIN 必须手写 XML SQL。2. 多表联查必踩坑MP 自动逻辑删除只对主表生效关联表必须手动加is_deleted0多表同名字段必须起别名否则映射冲突优先使用 LEFT JOIN保证主表数据不丢失3. 最终标准多表分页SQLselect idselectOrderVOPage resultTypeorg.example.c.backend.vo.OrderVO select s.id, s.order_no, c.name as customer_name, s.total_amount, s.status, s.create_time from sale_order s left join customer c on s.customer_id c.id AND c.is_deleted 0 where s.is_deleted 0 if testorderNo ! null and orderNo ! and s.order_no LIKE CONCAT(%,#{orderNo},%) /if /where order by s.create_time desc /select4. 下划线别名自动映射驼峰SpringBoot 默认开启驼峰转换customer_name自动映射 VO 中customerName无需手动适配。五、分页VO统一封装Service层完成数据组装1. 需求优化将分页组装、VO转换全部放在 ServiceController 极致精简只负责接收参数、返回结果。2. 通用 PageVO 工具类Data public class PageVOT { private ListT records; private long total; private long size; private long current; private long pages; // 通用转换方法 public static T, E PageVOT convert(IPageE iPage, ListT voList) { PageVOT pageVO new PageVO(); pageVO.setRecords(voList); pageVO.setTotal(iPage.getTotal()); pageVO.setSize(iPage.getSize()); pageVO.setCurrent(iPage.getCurrent()); pageVO.setPages(iPage.getPages()); return pageVO; } }3. Service 标准写法Override public PageVOOrderVO getOrderPage(Long current, Long size, String orderNo) { PageOrderVO pageParam new Page(current, size); baseMapper.selectOrderVOPage(pageParam, orderNo); // 直接返回组装好的分页数据Controller零处理 return PageVO.convert(pageParam, pageParam.getRecords()); }六、订单号生成避坑禁止 new Date().toString()1. 错误写法new Date().toString()生成带空格、冒号的字符串格式混乱且一秒内多订单会重复。2. 实战最优订单号// 时间三位随机数防重复 SimpleDateFormat sdf new SimpleDateFormat(yyyyMMddHHmmss); String timeStr sdf.format(new Date()); int random (int)(Math.random() * 1000); String orderNo timeStr random;七、订单库存事务一致性核心业务1. 业务要求保存订单、扣减库存必须原子执行库存不足则订单不生成订单失败则库存不扣减。2. 必须开启事务Transactional(rollbackFor Exception.class)解决默认事务只回滚运行时异常的问题所有异常全部回滚。3. 杜绝库存超卖终极方案禁止先查库存、内存计算、再更新并发必超卖推荐数据库原子扣减 库存判断boolean updateOk productService.lambdaUpdate() .setSql(stock stock - quantity) .eq(Product::getId, productId) .ge(Product::getStock, quantity) .update(); if (!updateOk) { throw new RuntimeException(商品库存不足); }4. 订单业务致命BUG修复错误顺序先循环生成订单项orderId为null→ 最后保存订单正确顺序先保存主订单获取ID → 再循环扣库存、生成订单项八、JSON List传参问题1. 问题前端传单个商品项数组后端 List 能否接收2. 答案完全可以JSON 数组长度为1合法只需杜绝空数组、多余逗号语法错误。3. 后端非空校验if(orderItems null || orderItems.isEmpty()){ throw new RuntimeException(请至少选择一件商品下单); }九、Controller 异常处理规范Service 只抛异常、不处理返回值Controller try-catch 捕获异常返回前端友好提示禁止吞异常必须抛出才能触发事务回滚增加登录session非空判断杜绝空指针十、全文核心总结必记MP3.5.9 必须额外引入 jsqlparser 分页依赖多表联查必须手写XML手动加关联表逻辑删除条件数据库下划线字段自动映射 Java 驼峰属性订单库存业务必须加事务 原子扣库存防超卖VO只存前端展示字段严格脱敏Service处理业务分页组装Controller保持极简订单生成必须先存主表、再存子项避免ID为null
返回列表