MyBatis-Plus常用技巧,助你开发效率翻倍!
告别重复SQL,这些技巧让你的DAO层开发事半功倍
在日常开发中,很多同学还在手写基础的增删改查代码,每个Mapper都要写XML、写SQL,重复劳动不说,还容易出错。今天就来聊聊MyBatis-Plus(简称MP)这款神器,看看它如何帮助我们真正解放生产力。
一、代码生成器:告别重复造轮子
这是MP最让人上头的功能之一。通过代码生成器,可以根据数据库表结构,一键生成Entity、Mapper、Service、Controller等各层代码,大幅减少基础编码工作
新版MP推荐使用 FastAutoGenerator,通过链式调用配置数据源、包路径和生成策略即可
FastAutoGenerator.create("jdbc:mysql://localhost:3306/db", "root", "123456")
.globalConfig(builder -> builder.author("你的名字").outputDir(System.getProperty("user.dir") + "/src/main/java"))
.packageConfig(builder -> builder.parent("com.example.project"))
.strategyConfig(builder -> builder.addInclude("user", "order"))
.execute();
使用代码生成器后,合理配置可减少约 70% 的基础代码编写量。不过需要提醒的是:生成的代码只是骨架,业务逻辑还是要自己动手哦。
二、条件构造器:复杂查询也能优雅编码
条件构造器是MP的灵魂所在,支持用面向对象的方式构建SQL条件,彻底告别手动拼接SQL的噩梦。
推荐优先使用 LambdaQueryWrapper,因为它通过方法引用来引用字段(如 User::getName),可以享受编译期检查的优势:
// ✅ 推荐:编译期检查字段有效性
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "张三")
.gt(User::getAge, 18)
.like(User::getEmail, "example.com")
.orderByDesc(User::getCreateTime);
List<User> users = userMapper.selectList(wrapper);
如果手头已经是QueryWrapper的代码也没关系,后续可以平滑迁移到Lambda版本,不需要改动业务逻辑。
三、自动填充:公共字段不再手动维护
在开发中,我们经常要维护 create_time、update_time、create_by、update_by 这类公共字段。MP的自动填充功能能自动处理这些字段,极大简化开发过程。
使用步骤超简单:
第一步:在实体类字段上添加 @TableField 注解:
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
第二步:实现 MetaObjectHandler 接口:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}
现在新增和更新时,这些字段就会自动填充啦,再也不用手动set了!
四、批量操作:大数据量场景的救星
在处理数据迁移、批量导入等场景时,逐条插入性能极差。MP的批量操作可以显著提升数据处理效率。
IService 提供了 saveBatch、updateBatchById 等方法,使用很方便:
// 批量新增,默认批次大小1000
userService.saveBatch(userList, 500);
但有个重要优化:MP的 saveBatch 方法内部实际上是循环单条插入再批量刷新。要获得真正的批量插入性能提升,需要在数据库连接URL中开启 rewriteBatchedStatements=true:
spring.datasource.url=jdbc:mysql://localhost:3306/db?rewriteBatchedStatements=true
开启后,多条INSERT语句会被合并为一条执行,性能大幅提升,某些场景下甚至能提升25倍以上。
五、分页插件:一行代码搞定分页查询
分页查询是每个项目的标配功能。MP的分页插件基于MyBatis物理分页,支持MySQL、Oracle等多种数据库。
首先注册分页插件:
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
然后在业务代码中直接调用:
Page<User> page = new Page<>(1, 10);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getStatus, 1);
Page<User> result = userMapper.selectPage(page, wrapper);
// 结果自动封装到Page对象中,包含records、total、pages等
六、防坑指南:这些坑99%的新手都踩过
1. 不要同时引入MyBatis和MyBatis-Plus的依赖
MP的starter已包含MyBatis核心包,同时引入会导致冲突。
2. 小心全表扫描
当 selectList 的 wrapper 参数为null时,会执行全表扫描,在大数据量下后果很严重。
3. 自动填充有默认策略
MetaObjectHandler 提供的默认方法策略是:如果属性已经有值则不会覆盖,如果填充值为null则不填充。这一点需要注意,避免预期与实际不符。
4. 批量操作的事务管理
批量操作默认不开启事务,需要手动管理以确保数据一致性。
5. 主键策略的选择
使用 @TableId 注解时,推荐使用 IdType.AUTO(数据库自增)或 IdType.ASSIGN_ID(雪花算法),避免使用 INPUT 导致忘记手动赋值。
总结
MyBatis-Plus通过无侵入的增强设计,在不改变现有代码结构的基础上,让DAO层开发效率大幅提升。
今天分享的这些技巧涵盖了代码生成、条件查询、字段填充、批量操作和分页查询等常用场景,掌握它们可以帮助你:
- 减少 70% 以上的重复代码编写
- 消除SQL拼接带来的隐患
- 提升批量数据处理性能
- 让团队编码更加规范和统一
如果你还没有在项目中使用MP,不妨从今天开始尝试。如果你已经在用,欢迎在评论区分享你的使用心得!
