视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)
一、为什么用 MyBatis-Plus?真实痛点 vs 神器
很多开发者还在手写 CRUD:
// 手写 Mapper XML,重复又易错 <select id="selectUserByName" resultType="User"> SELECT * FROM user WHERE name = #{name} </select>MyBatis-Plus(MP)是什么?
✅ 它是 MyBatis 的增强工具,在MyBatis 的基础上只做增强,不做改变。
✅ 自动注入通用 CRUD 方法,无需写 SQL,一行代码搞定增删改查!
🌰 场景:快速开发后台管理系统
- 用户管理、商品管理、订单管理……
- 每张表都要写 5~10 个基础接口
- 时间紧、任务重、还要防 SQL 注入
MP 方案:
// 继承 BaseMapper,直接拥有 20+ 个方法! public interface UserMapper extends BaseMapper<User> {}// 查询名字为 "张三" 的用户 List<User> users = userMapper.selectList( new QueryWrapper<User>().eq("name", "张三") );✅ 零 XML、零 SQL、类型安全、防注入!
二、Spring Boot + MyBatis-Plus 快速集成(正确姿势)
第一步:添加依赖(pom.xml)
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.5</version> </dependency> <!-- 数据库驱动(以 MySQL 为例) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>⚠️ 注意:不要同时引入
mybatis-spring-boot-starter,MP 已包含!
第二步:配置application.yml
spring: datasource: url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志 global-config: db-config: id-type: auto # 主键自增 table-prefix: t_ # 表名前缀(如实体类 User 对应 t_user)第三步:定义实体类(关键注解)
@Data @TableName("t_user") // 指定表名 public class User { @TableId(type = IdType.AUTO) // 主键策略 private Long id; @TableField("user_name") // 字段映射(数据库字段是 user_name) private String userName; private Integer age; @TableField(exist = false) // 非数据库字段(如密码确认) private String confirmPassword; }第四步:Mapper 接口(一行代码,功能全有)
@Mapper public interface UserMapper extends BaseMapper<User> { // 无需写任何方法!BaseMapper 已提供: // insert, deleteById, updateById, selectById, selectList... }第五步:Service 层(推荐使用 MP 的 IService)
@Service public class UserService implements IService<User> { @Autowired private UserMapper userMapper; // 可直接调用 getBaseMapper() 使用 CRUD public void demo() { // 插入 User user = new User(); user.setUserName("李四"); user.setAge(25); save(user); // 来自 IService // 查询 List<User> list = list(new QueryWrapper<User>() .ge("age", 18) .like("user_name", "李") ); } }✅ 优势:
IService提供更多便捷方法,如saveBatch、updateBatchById等。
三、高频反例 & 致命陷阱(90% 新手都中招!)
❌ 反例1:滥用select *,导致性能爆炸!
// 错误:查询所有字段,即使只需要 id 和 name List<User> users = userMapper.selectList(null);✅ 正确:只查需要的字段
// 方式1:QueryWrapper.select() List<User> users = userMapper.selectList( new QueryWrapper<User>().select("id", "user_name") ); // 方式2:自定义 DTO + @Select @Select("SELECT id, user_name FROM t_user WHERE age > #{age}") List<UserDTO> selectSimpleUsers(@Param("age") int age);❌ 反例2:手动拼接 SQL,引发注入漏洞!
// 危险!用户输入 "'; DROP TABLE t_user; --" 就完蛋了 String sql = "SELECT * FROM t_user WHERE name = '" + name + "'";✅ 正确:永远使用 Wrapper 或参数绑定
// 安全!MP 自动参数化 userMapper.selectList(new QueryWrapper<User>().eq("user_name", name));❌ 反例3:批量操作不用 MP 的 batch 方法 → 慢如蜗牛!
// 错误:循环单条插入(1万条 = 1万次数据库交互) for (User user : userList) { userMapper.insert(user); }✅ 正确:使用saveBatch
userService.saveBatch(userList, 1000); // 分批提交,每批1000条💡 原理:MP 内部使用
ExecutorType.BATCH,极大提升性能。
❌ 反例4:逻辑删除配置错误 → 数据“假删”变“真丢”!
// 实体类未加 @TableLogic private Integer deleted; // 0-正常,1-删除✅ 正确配置:
// 1. 实体类标注 @TableLogic private Integer deleted; // 2. 全局配置(application.yml) mybatis-plus: global-config: db-config: logic-delete-value: 1 # 删除值 logic-not-delete-value: 0 # 未删除值🔍 效果:
userMapper.deleteById(1)→ 实际执行UPDATE ... SET deleted = 1userMapper.selectById(1)→ 自动追加WHERE deleted = 0
❌ 反例5:分页插件未注册 → 分页失效!
// 直接调用 page 方法,结果返回全部数据! IPage<User> page = userService.page(new Page<>(1, 10));✅ 正确:必须注册分页插件
@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusIntercepter(); // 注意拼写! interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }⚠️ 注意:MP 3.4.0+ 使用
MybatisPlusInterceptor,旧版用PaginationInterceptor。
四、高级技巧:让 MP 更高效
1. 自动填充创建/更新时间
@TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class); this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); } }2. 乐观锁防止并发更新
@Version private Integer version; // 配置插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());五、总结:MyBatis-Plus 使用 Checklist
| 项目 | 正确做法 |
|---|---|
| 依赖 | 只引mybatis-plus-boot-starter |
| 主键 | 用@TableId明确策略 |
| 字段映射 | 用@TableField处理下划线 |
| 查询 | 用QueryWrapper,禁止字符串拼接 |
| 批量 | 用saveBatch/updateBatchById |
| 分页 | 注册PaginationInnerInterceptor |
| 逻辑删除 | 配置@TableLogic+ 全局规则 |
| 性能 | 避免select *,只查必要字段 |
MyBatis-Plus 不是“魔法”,而是规范 + 约定。
用对了,开发效率翻倍;用错了,埋下性能炸弹!
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)