1. MybatisPlus代码生成器概述
MybatisPlus代码生成器是一个基于MybatisPlus框架的自动化代码生成工具,它能够根据数据库表结构自动生成Entity、Mapper、Service、Controller等基础代码。作为Mybatis的增强工具,MybatisPlus在简化开发流程、提高开发效率方面表现出色,而代码生成器则是这一理念的集中体现。
在实际开发中,我们经常需要为数据库中的每张表编写重复的基础代码。这个过程不仅耗时耗力,而且容易出错。MybatisPlus代码生成器通过自动化这一过程,可以节省开发者约70%的基础代码编写时间。它支持多种数据库(MySQL、Oracle、SQL Server等),能够根据表结构自动生成包含基本CRUD操作的完整代码框架。
提示:虽然代码生成器能极大提高效率,但生成的代码通常需要根据具体业务需求进行二次调整,不建议直接在生产环境中使用未经修改的生成代码。
2. 核心功能与实现原理
2.1 代码生成器的工作流程
MybatisPlus代码生成器的核心工作流程可以分为以下几个步骤:
数据库连接与元数据获取:首先需要配置数据库连接信息,代码生成器通过JDBC连接数据库,获取数据库的元数据信息,包括表结构、字段类型、主键信息等。
模板解析与代码生成:获取到表结构信息后,代码生成器会根据内置的Velocity模板引擎,将数据库表结构信息填充到预设的代码模板中。
文件输出:生成的代码会按照预设的包结构输出到指定目录,通常包括:
- Entity:对应数据库表的实体类
- Mapper:数据库操作接口
- Service:业务服务层接口和实现
- Controller:Web层控制器
2.2 核心配置参数解析
在使用MybatisPlus代码生成器时,有几个关键配置参数需要特别注意:
// 代码生成器配置示例 AutoGenerator generator = new AutoGenerator(); // 全局配置 GlobalConfig globalConfig = new GlobalConfig(); globalConfig.setOutputDir("src/main/java"); globalConfig.setAuthor("YourName"); globalConfig.setOpen(false); generator.setGlobalConfig(globalConfig); // 数据源配置 DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/your_db"); dataSourceConfig.setDriverName("com.mysql.jdbc.Driver"); dataSourceConfig.setUsername("root"); dataSourceConfig.setPassword("password"); generator.setDataSource(dataSourceConfig); // 包配置 PackageConfig packageConfig = new PackageConfig(); packageConfig.setParent("com.your.package"); generator.setPackageInfo(packageConfig); // 策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); strategy.setRestControllerStyle(true); generator.setStrategy(strategy); generator.execute();3. 高级功能与定制化
3.1 自定义模板引擎
MybatisPlus默认使用Velocity作为模板引擎,但也支持Freemarker和Beetl。如果需要自定义模板,可以按照以下步骤操作:
- 在resources目录下创建templates文件夹
- 复制MybatisPlus提供的默认模板到该目录
- 修改模板内容以满足特定需求
- 在代码生成器配置中指定模板路径
// 自定义模板配置示例 TemplateConfig templateConfig = new TemplateConfig(); templateConfig.setEntity("templates/entity.java"); templateConfig.setMapper("templates/mapper.java"); templateConfig.setService("templates/service.java"); templateConfig.setController("templates/controller.java"); generator.setTemplate(templateConfig);3.2 动态条件查询生成
MybatisPlus代码生成器可以自动生成基于Wrapper的条件查询方法。在策略配置中,可以通过以下方式启用:
StrategyConfig strategy = new StrategyConfig(); strategy.setSuperEntityClass("com.your.package.BaseEntity"); strategy.setSuperServiceClass("com.your.package.BaseService"); strategy.setSuperServiceImplClass("com.your.package.BaseServiceImpl"); strategy.setSuperControllerClass("com.your.package.BaseController");这样生成的代码会包含常用的条件查询方法,如:
// 生成的查询方法示例 public List<User> listUsers(String name, Integer age) { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(name), "name", name); wrapper.ge(age != null, "age", age); return userMapper.selectList(wrapper); }4. 实战技巧与常见问题
4.1 分页功能实现
MybatisPlus提供了强大的分页功能,代码生成器可以自动配置分页插件。需要在生成代码前配置分页插件:
// 分页插件配置 @Configuration public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求 paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认500条 paginationInterceptor.setLimit(500); return paginationInterceptor; } }生成的分页查询代码示例:
// 分页查询示例 public Page<User> pageUsers(int current, int size, String name) { Page<User> page = new Page<>(current, size); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(name), "name", name); return userMapper.selectPage(page, wrapper); }4.2 字段更新策略
MybatisPlus默认的更新策略是忽略null值字段,这在某些场景下可能不符合需求。可以通过以下方式修改:
// 全局配置null值更新策略 globalConfig.setDbConfig(new GlobalConfig.DbConfig() .setLogicDeleteField("deleted") // 逻辑删除字段 .setVersionField("version") // 乐观锁字段 .setInsertStrategy(DbConfig.InsertStrategy.NOT_NULL) .setUpdateStrategy(DbConfig.UpdateStrategy.NOT_NULL));如果需要更新字段为null,可以使用以下方式:
// 强制更新null值字段 UpdateWrapper<User> wrapper = new UpdateWrapper<>(); wrapper.set("name", null); userMapper.update(null, wrapper);5. 性能优化与最佳实践
5.1 批量操作优化
MybatisPlus提供了批量操作方法,可以显著提高大批量数据操作的性能:
// 批量插入示例 public boolean batchInsert(List<User> users) { return userService.saveBatch(users, 1000); // 每批1000条 } // 批量更新示例 public boolean batchUpdate(List<User> users) { return userService.updateBatchById(users, 1000); }注意:批量操作时建议合理设置批次大小,过大的批次可能导致内存溢出,过小的批次则影响性能。
5.2 多数据源配置
对于需要连接多个数据库的项目,可以配置多数据源:
// 多数据源配置示例 @Configuration @MapperScan(basePackages = "com.your.package.mapper.db1", sqlSessionTemplateRef = "db1SqlSessionTemplate") public class Db1DataSourceConfig { @Bean(name = "db1DataSource") @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource db1DataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "db1SqlSessionFactory") public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); return factoryBean.getObject(); } @Bean(name = "db1SqlSessionTemplate") public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }6. 常见问题排查
6.1 生成的代码不符合预期
可能原因及解决方案:
- 数据库连接问题:检查数据库URL、用户名和密码是否正确
- 表名大小写问题:MySQL在Linux下区分大小写,确保表名正确
- 策略配置错误:检查StrategyConfig中的命名策略等配置
6.2 分页查询不生效
排查步骤:
- 确认已配置分页插件
- 检查Page对象参数是否正确传递
- 确保SQL中没有语法错误
6.3 字段更新策略问题
如果发现null值字段未被更新:
- 检查全局配置中的更新策略
- 确认是否使用了UpdateWrapper明确指定了要更新的字段
- 检查实体类字段是否有@TableField注解的特殊配置
7. 单元测试与代码质量
7.1 生成代码的单元测试
MybatisPlus生成的代码应该包含基本的单元测试:
@SpringBootTest public class UserServiceTest { @Autowired private UserService userService; @Test public void testGetById() { User user = userService.getById(1L); Assert.assertNotNull(user); } @Test public void testPage() { Page<User> page = new Page<>(1, 10); Page<User> result = userService.page(page); Assert.assertEquals(10, result.getRecords().size()); } }7.2 代码质量检查建议
- 生成的Entity类:检查是否添加了必要的校验注解,如@NotBlank、@Size等
- Service层:确认业务逻辑是否完整,是否需要添加事务注解
- Controller层:检查是否添加了合适的API注解,如@ApiOperation等
- 异常处理:确保有统一的异常处理机制
8. 进阶应用与扩展
8.1 动态表名处理
对于需要动态切换表名的场景,可以实现动态表名处理器:
public class DynamicTableNameParser implements ITableNameHandler { @Override public String dynamicTableName(String sql, String tableName) { // 根据业务逻辑返回动态表名 return getCurrentTableName(tableName); } private String getCurrentTableName(String originalName) { // 实现动态表名逻辑 return originalName + "_" + getCurrentYear(); } } // 配置动态表名拦截器 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser(); interceptor.addInnerInterceptor(dynamicTableNameParser); return interceptor; }8.2 多租户支持
MybatisPlus支持多租户架构,可以通过以下方式配置:
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 多租户拦截器 TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor(); tenantInterceptor.setTenantLineHandler(new TenantLineHandler() { @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public Expression getTenantId() { return new StringValue(getCurrentTenantId()); } @Override public boolean ignoreTable(String tableName) { // 指定不需要多租户过滤的表 return "tenant".equals(tableName); } }); interceptor.addInnerInterceptor(tenantInterceptor); return interceptor; }9. 安全注意事项
9.1 防止全表删除
MybatisPlus提供了防止全表删除的插件:
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 阻止全表更新和删除 interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); return interceptor; }9.2 SQL注入防护
虽然MybatisPlus使用预编译语句可以有效防止SQL注入,但仍需注意:
- 避免直接拼接SQL语句
- 使用Wrapper构建查询条件而非字符串拼接
- 对用户输入进行严格的参数校验
10. 性能监控与调优
10.1 SQL执行监控
可以配置SQL执行分析插件来监控SQL性能:
@Bean @Profile({"dev", "test"}) // 只在开发和测试环境启用 public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor interceptor = new PerformanceInterceptor(); interceptor.setMaxTime(1000); // SQL执行最大时长,超过自动停止运行 interceptor.setFormat(true); // 是否格式化SQL return interceptor; }10.2 二级缓存配置
合理使用二级缓存可以提高查询性能:
@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager() { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) .disableCachingNullValues(); return RedisCacheManager.builder(redisConnectionFactory()) .cacheDefaults(config) .build(); } } // 在Mapper接口上添加缓存注解 @CacheNamespace public interface UserMapper extends BaseMapper<User> { }在实际项目中,我发现合理使用MybatisPlus代码生成器可以节省大量重复劳动时间,但需要注意生成的代码只是基础框架,必须根据实际业务需求进行定制化调整。特别是在复杂的业务场景中,不能过度依赖自动生成的代码,而应该将其作为起点,在此基础上构建更健壮的业务逻辑。