下面是对 MyBatis-Plus 代码生成器(Code Generator)原理的深度源码分析,涵盖其设计思想、核心组件、执行流程、关键技术(如模板引擎、元数据读取)以及如何实现“一键生成”Entity、Mapper、Service、Controller 等全套代码。
🌟 一、MyBatis-Plus 代码生成器简介
MyBatis-Plus Code Generator 是一个基于数据库表结构,自动生成 Java 代码 的工具,支持:
- 实体类(Entity)
- Mapper 接口
- Mapper XML 文件
- Service 接口与实现类
- Controller 类
- 前端 Vue 页面(可选)
它极大提升了开发效率,尤其适用于 CRUD 为主的项目。
🧩 二、核心目标
| 目标 | 说明 |
|---|---|
| 减少样板代码 | 不用手动创建 Entity、Mapper 等 |
| 统一命名规范 | 字段驼峰、表前缀自动去除等 |
| 集成 MP 特性 | 如 @TableField(fill = FieldFill.INSERT) 自动填充 |
| 支持多种模板引擎 | 默认使用 Freemarker,也支持 Velocity、Beetl 等 |
🔧 三、整体架构与核心组件
graph TD
A[代码生成器入口] --> B[AutoGenerator]
B --> C[GlobalConfig] 全局配置(作者、输出目录)
B --> D[DataSourceConfig] 数据源配置(连接数据库)
B --> E[PackageConfig] 包名配置(com.example.entity 等)
B --> F[StrategyConfig] 策略配置(表名、字段命名规则)
B --> G[TemplateEngine] 模板引擎(Freemarker)
G --> H[模板文件 ftl] 如 entity.java.ftl
B --> I[InjectionConfig] 自定义注入(可扩展)
🚀 四、执行流程源码剖析
1. 入口类:AutoGenerator
AutoGenerator generator = new AutoGenerator();
generator.setGlobalConfig(globalConfig);
generator.setDataSource(dataSourceConfig);
generator.setPackageInfo(packageConfig);
generator.setStrategy(strategyConfig);
generator.setTemplateEngine(new FreemarkerTemplateEngine()); // 模板引擎
generator.execute(); // 执行生成
2. execute() 核心流程
🧠 五、核心组件详解
1. DataSourceConfig —— 数据库连接配置
DataSourceConfig dsc = new DataSourceConfig.Builder("jdbc:mysql://localhost:3306/test", "root", "123456")
.build();
- 用于连接数据库,读取
information_schema获取表结构。 - 支持 MySQL、Oracle、PostgreSQL、SQL Server 等。
2. StrategyConfig —— 生成策略配置
StrategyConfig strategy = new StrategyConfig.Builder()
.addInclude("t_user", "t_order") // 包含的表
.addTablePrefix("t_") // 忽略表前缀
.entityBuilder()
.enableLombok() // 启用 Lombok
.logicDeleteColumnName("deleted") // 逻辑删除字段
.naming(NamingStrategy.underline_to_camel) // 下划线转驼峰
.columnNaming(NamingStrategy.underline_to_camel)
.serviceBuilder()
.formatServiceFileName("%sService") // Service 接口命名
.controllerBuilder()
.enableRestStyle() // 使用 @RestController
.build();
✅ 策略决定:类名、字段名、是否生成某类文件等。
3. GlobalConfig —— 全局配置
GlobalConfig gc = new GlobalConfig.Builder()
.outputDir(System.getProperty("user.dir") + "/src/main/java")
.author("zhangsan")
.enableSwagger() // 启用 Swagger 注解
.commentDate("yyyy-MM-dd") // 注释日期格式
.build();
4. PackageConfig —— 包名配置
PackageConfig pc = new PackageConfig.Builder()
.parent("com.example")
.entity("entity")
.mapper("mapper")
.service("service")
.controller("controller")
.build();
5. TemplateEngine —— 模板引擎(Freemarker)
- MP 默认使用 Freemarker 模板引擎。
- 模板文件位于:
resources/templates/entity.java.ftl—— 实体类模板mapper.java.ftl—— Mapper 接口mapper.xml.ftl—— XML 映射文件service.java.ftl,service.impl.java.ftlcontroller.java.ftl
示例:entity.java.ftl
package ${package.Entity};
<#if entityLombokModel>
import lombok.Data;
import lombok.EqualsAndHashCode;
</#if>
@Data
<#if superEntityClass??>
@EqualsAndHashCode(callSuper = true)
</#if>
<#if entityTableFieldAnnotationEnable>
import com.baomidou.mybatisplus.annotation.*;
</#if>
<#list table.importPackages as pkg>
import ${pkg};
</#list>
/**
* <p>
* ${table.comment!}
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}><#else> </#if> {
<#else>
public class ${entity} {
</#if>
<#-- 循环字段生成属性 -->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}">
</#if>
<#if field.comment??>
/**
* ${field.comment}
*/
</#if>
<#if field.annotationEnum??>
<#list field.annotationEnum?values as ann>
${ann}\
</#list>
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
</#list>
✅ 通过
TableInfo对象填充模板变量(如${entity},${table.fields})。
6. TableInfo —— 表结构元数据模型
public class TableInfo {
private String name; // 表名
private String comment; // 表注释
private String entityName; // 生成的类名
private List<TableField> fields; // 字段列表
private TableField keyField; // 主键字段
// ...
}
每个字段 TableField 包含:
- 列名、属性名、类型(Java 类型)
- 是否主键、是否自增
- 是否逻辑删除
- 填充策略(
FieldFill.INSERT) - 注解信息(如
@TableId,@TableField)
🧩 六、关键技术点
| 技术 | 说明 |
|---|---|
| JDBC 元数据读取 | 使用 DatabaseMetaData 或直接查 information_schema 获取表结构 |
| 模板引擎渲染 | Freemarker 将 TableInfo 与 .ftl 模板合并生成代码 |
| 命名策略转换 | 如 user_name → userName(下划线转驼峰) |
| 自动识别主键 | 支持 @TableId(type = IdType.AUTO) 等策略 |
| 可扩展性 | 支持自定义模板、自定义 InjectionConfig 注入额外属性 |
✅ 七、自定义扩展(高级用法)
1. 自定义模板路径
templateConfig.entity("templates/my_entity.java.ftl");
generator.setTemplate(templateConfig);
2. 自定义输出内容(InjectionConfig)
InjectionConfig cfg = new InjectionConfig.Builder()
.beforeOutputData((tableInfo, objectMap) -> {
objectMap.put("customAuthor", "admin");
objectMap.put("needAudit", true);
})
.build();
可在模板中使用 ${customAuthor}。
🛑 八、常见问题与坑点
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 生成字段类型错误 | 数据库类型映射配置缺失 | 自定义 TypeConvertHandler |
| 注释未生成 | 表/字段无 COMMENT | 在数据库中添加注释 |
| Lombok 不生效 | 缺少依赖 | 手动添加 lombok 依赖 |
| 模板找不到 | 路径错误 | 将模板放在 resources/templates/ |
✅ 总结:MyBatis-Plus 代码生成器的本质
Code Generator = 元数据读取 + 策略映射 + 模板引擎 + 文件生成
| 核心思想 | 说明 |
|---|---|
| 元数据驱动 | 从数据库读取结构,避免手动输入 |
| 模板化生成 | 使用 Freemarker 实现灵活输出 |
| 约定优于配置 | 提供合理的默认命名、注解 |
| 高度可扩展 | 支持自定义模板、策略、注入逻辑 |
原理的深度源码分析&spm=1001.2101.3001.5002&articleId=150203169&d=1&t=3&u=e50bdda700bb4d66a5ae409b1ce83895)
2995

被折叠的 条评论
为什么被折叠?



