1. MyBatis-Plus核心价值与定位
MyBatis-Plus作为MyBatis的增强工具,在保留MyBatis所有特性的基础上,针对单表CRUD操作进行了深度封装。最新3.5.x版本通过Lambda表达式和链式调用,让基础数据操作代码量减少50%以上。与Spring Boot的版本对应关系为:3.5.x建议搭配Spring Boot 2.7.x使用,这是目前企业级项目中最稳定的组合方案。
注意:若依框架4.8.3版本迁移时,需特别注意XML映射文件和注解的兼容性问题,建议先在新分支进行完整测试
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境搭建
2.1 依赖配置要点
在pom.xml中需要包含以下核心依赖(以Spring Boot 2.7.18为例):
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
<scope>provided</scope>
</dependency>
2.2 配置类关键参数
在application.yml中必须配置的项包括:
yaml复制mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # SQL日志输出
global-config:
db-config:
id-type: auto # 主键策略
logic-delete-field: deleted # 逻辑删除字段
logic-not-delete-value: 0
logic-delete-value: 1
3. 实体层设计规范
3.1 注解使用实践
标准实体类应包含以下核心注解:
java复制@Data
@TableName("sys_user") // 显式指定表名
public class User {
@TableId(type = IdType.AUTO) // 主键策略
private Long id;
@TableField("username") // 字段映射
private String name;
@TableField(fill = FieldFill.INSERT) // 自动填充
private LocalDateTime createTime;
@Version // 乐观锁
private Integer version;
}
3.2 类型处理器配置
对于特殊字段类型(如枚举、JSON等),需要注册类型处理器:
java复制@Bean
public MybatisPlusSqlInjector sqlInjector() {
return new MybatisPlusSqlInjector() {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new InsertBatchSomeColumn()); // 批量插入方法
return methodList;
}
};
}
4. CRUD操作深度解析
4.1 插入操作优化
批量插入的性能对比(测试数据量10万条):
| 操作方式 | 耗时(ms) | 内存占用(MB) |
|---|---|---|
| 循环单条插入 | 28500 | 120 |
| MP批量插入 | 3200 | 85 |
| 原生批量语句 | 2100 | 65 |
推荐使用Service层的saveBatch方法:
java复制userService.saveBatch(userList, 1000); // 每批1000条提交
4.2 更新操作策略
动态更新字段的两种实现方式:
java复制// 方式1:UpdateWrapper动态构建
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("status", 1)
.set("login_count", 0)
.setSql("balance = balance + 100");
// 方式2:Lambda表达式
LambdaUpdateWrapper<User> lambdaWrapper = Wrappers.lambdaUpdate();
lambdaWrapper.eq(User::getStatus, 1)
.set(User::getLoginCount, 0)
.setSql("balance = balance + 100");
5. 查询功能进阶
5.1 分页查询实现
分页插件配置类示例:
java复制@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL){
@Override
protected void optimizeCount(IPage<?> page, MappedStatement ms, BoundSql boundSql) {
// 优化COUNT查询
}
});
return interceptor;
}
}
5.2 复杂查询构建
多表关联查询的两种方案对比:
- 注解方式(适合简单关联):
java复制@Select("select u.*, d.dept_name from user u left join dept d on u.dept_id=d.id")
List<UserVO> selectUserWithDept();
- XML方式(适合复杂SQL):
xml复制<select id="selectComplexUser" resultMap="userResultMap">
select
<include refid="userColumns"/>,
<include refid="deptColumns"/>
from sys_user u
left join sys_dept d on u.dept_id=d.id
where ${ew.sqlSegment}
</select>
6. 企业级实践技巧
6.1 多租户方案实现
基于TenantLineInnerInterceptor的租户隔离:
java复制interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public Expression getTenantId() {
return new LongValue(1L); // 实际应从上下文中获取
}
@Override
public boolean ignoreTable(String tableName) {
return !Arrays.asList("user","order").contains(tableName);
}
}));
6.2 审计字段自动填充
实现MetaObjectHandler处理创建/修改信息:
java复制@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createBy", String.class, getCurrentUser());
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateBy", String.class, getCurrentUser());
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
7. 性能优化指南
7.1 SQL执行分析
启用性能分析插件:
java复制interceptor.addInnerInterceptor(new PerformanceInnerInterceptor(){
@Override
protected void beforeQuery(StatementHandler statementHandler) {
// 可添加自定义监控逻辑
}
});
7.2 二级缓存配置
Redis缓存集成方案:
yaml复制mybatis-plus:
configuration:
cache-enabled: true
local-cache-scope: statement
java复制@CacheNamespace(implementation = MybatisRedisCache.class, eviction = MybatisRedisCache.class)
public interface UserMapper extends BaseMapper<User> {}
8. 常见问题排查
8.1 版本冲突解决
典型版本兼容问题处理:
- Spring Boot 2.7.x + MyBatis-Plus 3.5.x = 稳定组合
- 若依框架迁移时需检查:
- PageHelper与MP分页插件冲突
- MyBatis原生注解与MP注解混用问题
- XML中特殊语法的兼容性
8.2 事务管理要点
多数据源事务控制方案:
java复制@DS("master") // 指定数据源
@Transactional(rollbackFor = Exception.class)
public void crossDbOperation() {
masterMapper.insert(entity);
slaveMapper.update(entity);
}
9. 代码生成器实战
9.1 生成器配置模板
快速生成领域代码的配置示例:
java复制FastAutoGenerator.create(dataSourceConfig)
.globalConfig(builder -> builder.author("dev").outputDir("/src/main/java"))
.packageConfig(builder -> builder.parent("com.example"))
.strategyConfig(builder -> builder
.addInclude("user","role")
.entityBuilder()
.enableLombok()
.versionColumnName("version")
.logicDeleteColumnName("deleted")
)
.templateConfig(builder -> builder.disable(TemplateType.CONTROLLER))
.execute();
9.2 自定义模板修改
重写Entity模板示例:
java复制.templateEngine(new FreemarkerTemplateEngine() {
@Override
public String templateFilePath(String filePath) {
if (filePath.contains("entity.java.ftl")) {
return "/templates/my-entity.java.ftl";
}
return super.templateFilePath(filePath);
}
})
10. 扩展功能集成
10.1 多数据源动态切换
基于@DS注解的实现原理:
- 创建DynamicDataSourceProvider接口实现类
- 配置AbstractRoutingDataSource
- 通过AOP拦截@DS注解
10.2 数据权限控制
基于SQL拦截器的方案:
java复制interceptor.addInnerInterceptor(new DataPermissionInterceptor(new DataPermissionHandler() {
@Override
public Expression getSqlSegment(Table table, WhereSegment whereSegment) {
if ("sys_user".equals(table.getTableName())) {
return new StringValue("dept_id in (1,2,3)");
}
return null;
}
}));
11. 监控与诊断
11.1 慢SQL监控
结合Prometheus的监控方案:
java复制@Bean
public CollectorRegistry collectorRegistry() {
CollectorRegistry registry = new CollectorRegistry();
registry.register(new MybatisPlusMetricsCollector(sqlSessionFactory));
return registry;
}
11.2 执行计划分析
通过Explain注解获取执行计划:
java复制@Select("EXPLAIN FORMAT=JSON ${sql}")
String explainSql(@Param("sql") String sql);
12. 最佳实践总结
-
项目规范:
- 统一使用Lambda表达式写法
- 禁止在Service层直接使用QueryWrapper
- 复杂查询必须走XML方式
-
性能守则:
- 批量操作必须使用专用方法
- 查询必须明确指定字段列表
- 禁用SELECT * 查询
-
扩展建议:
- 多租户项目优先考虑SAAS模式
- 报表类查询建议使用原生SQL
- 高频查询应配置二级缓存
