
1. 项目背景与核心价值Spring Boot 3.3.X作为当前Java生态中最主流的应用开发框架其与MyBatis-Plus的组合堪称企业级开发的黄金搭档。最近在重构一个老项目时我再次验证了这套技术栈的威力——原本需要200行的JDBC模板代码用MyBatis-Plus只需要10行注解就能搞定。这种开发效率的提升对于应对互联网时代快速迭代的需求至关重要。MyBatis-Plus 3.5.3版本针对Spring Boot 3.x的自动配置做了深度优化特别是在动态数据源、多租户等企业级场景下表现出色。本文将基于最新稳定版演示如何实现二者的无缝整合并分享我在实际项目中总结的五个关键配置技巧。2. 环境准备与工程搭建2.1 依赖配置要点创建Spring Boot项目时建议使用最新的3.3.0版本。在pom.xml中需要特别注意以下依赖项dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- 必须添加的配套依赖 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.3.1/version scopecompile/scope /dependency重要提示Spring Boot 3.x默认使用Jakarta EE 9需要确保所有相关依赖如JDBC驱动也兼容Jakarta命名空间。常见的坑是引入老版本的druid等连接池会导致类加载冲突。2.2 配置文件关键参数在application.yml中以下配置项直接影响MyBatis-Plus的行为mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开发环境建议开启 map-underscore-to-camel-case: true # 必须开启的驼峰转换 global-config: db-config: logic-delete-field: deleted # 逻辑删除字段名 logic-not-delete-value: 0 logic-delete-value: 13. 核心功能实现详解3.1 实体类与Mapper配置实体类定义时需要特别注意Lombok注解与MyBatis-Plus注解的配合Data TableName(value sys_user, autoResultMap true) public class User { TableId(type IdType.AUTO) private Long id; TableField(value user_name, condition SqlCondition.LIKE) private String username; TableLogic private Integer deleted; }Mapper接口只需要继承BaseMapper即可获得CRUD能力Mapper public interface UserMapper extends BaseMapperUser { // 自定义方法示例 Select(SELECT * FROM sys_user WHERE age #{age}) ListUser selectByAge(Param(age) Integer age); }3.2 分页插件最佳实践分页配置需要特别注意高并发场景下的优化Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件必须放在第一位 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL){ Override public void optimizeCount(boolean optimizeCount) { // 大数据量时关闭count优化 if(tableSize 1000000) { super.optimizeCount(false); } } }); // 乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }4. 高级特性实战4.1 动态表名处理在SAAS多租户系统中动态表名是常见需求。通过实现TableNameHandler接口public class TenantTableNameHandler implements TableNameHandler { private final ThreadLocalString tenantId new ThreadLocal(); Override public String dynamicTableName(String sql, String tableName) { return Optional.ofNullable(tenantId.get()) .map(id - id _ tableName) .orElse(tableName); } }然后在配置类中注册Bean public DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() { DynamicTableNameInnerInterceptor interceptor new DynamicTableNameInnerInterceptor(); interceptor.setTableNameHandler(new TenantTableNameHandler()); return interceptor; }4.2 多数据源配置结合Spring Boot的AbstractRoutingDataSource实现Configuration MapperScan(basePackages com.example.mapper) public class DataSourceConfig { Bean ConfigurationProperties(prefix spring.datasource.master) public DataSource masterDataSource() { return DruidDataSourceBuilder.create().build(); } Bean ConfigurationProperties(prefix spring.datasource.slave) public DataSource slaveDataSource() { return DruidDataSourceBuilder.create().build(); } Bean public DataSource dynamicDataSource() { MapObject, Object targetDataSources new HashMap(); targetDataSources.put(master, masterDataSource()); targetDataSources.put(slave, slaveDataSource()); return new DynamicDataSource(masterDataSource(), targetDataSources); } }5. 性能优化与问题排查5.1 SQL注入防护MyBatis-Plus虽然提供了Wrapper构建安全查询但仍需注意// 错误示例存在注入风险 QueryWrapperUser wrapper new QueryWrapper(); wrapper.apply(date_format(create_time,%Y-%m-%d) date ); // 正确写法 wrapper.apply(date_format(create_time,%Y-%m-%d) {0}, date);5.2 批量操作优化使用ExecuteBatch批量执行器可以显著提升性能Test void testBatch() { String sqlStatement com.example.mapper.UserMapper.updateById; SqlSessionFactory sqlSessionFactory ...; try (SqlSession batchSession sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper batchSession.getMapper(UserMapper.class); for (int i 0; i 1000; i) { User user new User(); // ...set properties mapper.updateById(user); } batchSession.commit(); } }6. 常见问题解决方案6.1 类型处理器问题处理JSON字段时推荐使用JacksonTypeHandlerTableField(typeHandler JacksonTypeHandler.class) private MapString, Object attributes;需要在配置类中注册Bean public MybatisPlusSqlInjector mybatisPlusSqlInjector() { return new MybatisPlusSqlInjector() { Override public ListAbstractJsonTypeHandler? getTypeHandlers() { return Arrays.asList( new JacksonTypeHandler(), new FastjsonTypeHandler() ); } }; }6.2 事务失效场景多数据源环境下需要明确指定事务管理器Transactional(transactionManager masterTransactionManager) public void businessMethod() { // 操作master数据源 masterMapper.insert(...); // 操作slave数据源 slaveMapper.select(...); }在项目实际落地过程中我发现合理使用MyBatis-Plus的Lambda表达式可以大幅提升代码可读性。特别是在复杂查询场景下相比原生MyBatis的XML配置方式LambdaQueryWrapper能让代码逻辑更集中、更类型安全。比如处理多表关联查询时可以这样构建查询条件ListUser users userMapper.selectList(new LambdaQueryWrapperUser() .eq(User::getStatus, 1) .inSql(User::getDeptId, SELECT id FROM sys_dept WHERE status 1) .orderByDesc(User::getCreateTime) .last(LIMIT 10));这种链式调用的写法不仅直观还能利用IDE的代码提示和编译时类型检查有效减少运行时错误。对于需要频繁变动的查询条件建议封装成Builder模式进一步提高代码的可维护性。