一、核心概念
1. 模板引擎
- 作用:将数据库元数据与模板结合,动态生成代码文件
- 核心组件:
- 模板文件(.ftl/.vm):包含代码结构和占位符
- 数据模型:包含表结构、字段信息等元数据
- 引擎处理器:将数据注入模板生成最终代码
2. MyBatis-Plus支持
- 内置引擎:
FreemarkerTemplateEngine
(推荐)
VelocityTemplateEngine
BeetlTemplateEngine
- 默认模板路径:
resources/templates
- 文件扩展名:
- Freemarker:
.ftl
- Velocity:
.vm
二、详细操作步骤
步骤1:添加依赖
<!-- Freemarker 依赖 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<!-- Velocity 依赖 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!-- MyBatis-Plus 生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>
步骤2:配置模板引擎
// Freemarker 配置
AutoGenerator generator = new AutoGenerator();
generator.setTemplateEngine(new FreemarkerTemplateEngine());
// 或 Velocity 配置
// generator.setTemplateEngine(new VelocityTemplateEngine());
// 自定义模板路径(可选)
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setEntity("templates/my-entity.java.ftl"); // 自定义实体模板
generator.setTemplate(templateConfig);
步骤3:创建自定义模板
Freemarker模板示例 (resources/templates/my-entity.java.ftl
)
package ${package.Entity};
<#list table.importPackages as pkg>
import ${pkg};
</#list>
/**
* <p>
* ${table.comment!}
* </p>
*/
@Data
@TableName("${table.name}")
public class ${entity} implements Serializable {
private static final long serialVersionUID = 1L;
<#-- 主键字段 -->
<#list table.fields as field>
<#if field.keyFlag>
@TableId(value = "${field.name}", type = IdType.${idType})
</#if>
</#list>
<#-- 普通字段 -->
<#list table.commonFields as field>
/**
* ${field.comment!}
*/
@TableField("${field.name}")
private ${field.propertyType} ${field.propertyName};
</#list>
<#-- 版本控制字段 -->
<#if table.versionFieldName??>
@Version
private Integer version;
</#if>
<#-- 逻辑删除字段 -->
<#if table.logicDeleteFieldName??>
@TableLogic
private Integer deleted;
</#if>
}
步骤4:配置生成器使用自定义模板
public class CodeGenerator {
public static void main(String[] args) {
// ... [数据源配置、全局配置省略] ...
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setInclude("user", "order");
// 模板配置
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setEntity("templates/my-entity.java.ftl"); // 自定义实体模板
templateConfig.setMapper("templates/mapper.java.ftl"); // 自定义Mapper模板
AutoGenerator generator = new AutoGenerator();
generator.setTemplate(templateConfig);
generator.setTemplateEngine(new FreemarkerTemplateEngine());
// ... [执行生成] ...
}
}
步骤5:模板变量参考
变量名 |
描述 |
示例值 |
package.Entity |
实体类包名 |
com.example.entity |
entity |
实体类名 |
User |
table.name |
数据库表名 |
tbl_user |
table.comment |
表注释 |
用户信息表 |
field.name |
数据库字段名 |
user_name |
field.propertyName |
实体类属性名 |
userName |
field.propertyType |
属性类型 |
String |
field.comment |
字段注释 |
用户名 |
三、常见错误及解决方案
1. 模板文件找不到
2. 模板变量解析失败
3. 生成文件编码问题
- 现象:中文乱码
- 解决:
// 全局配置中设置编码
globalConfig.setCharset("UTF-8");
// 模板引擎设置编码(Velocity)
Properties props = new Properties();
props.put("input.encoding", "UTF-8");
props.put("output.encoding", "UTF-8");
generator.setTemplateEngine(new VelocityTemplateEngine(props));
4. 模板缓存问题
四、注意事项
1. 模板路径优先级
- 自定义路径 > resources/templates > 内置模板
- 未配置的模板使用默认生成器
2. 多模板引擎共存
// 不同文件类型使用不同引擎
generator.setTemplateEngine(new MultiTemplateEngine()
.register("ftl", new FreemarkerTemplateEngine())
.register("vm", new VelocityTemplateEngine()));
3. 敏感信息处理
<#-- 避免输出密码字段 -->
<#list table.fields as field>
<#if field.name?contains("password")>
@TableField(exist = false)
<#else>
@TableField("${field.name}")
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
五、高级使用技巧
1. 自定义模板函数
// 注册自定义方法
public class CustomFreemarkerEngine extends FreemarkerTemplateEngine {
@Override
public void init(Configuration config) {
config.setSharedVariable("toCamelCase", new TemplateMethodModelEx() {
public Object exec(List args) {
return NamingStrategy.capitalFirst(NamingStrategy.underlineToCamel((String) args.get(0)));
}
});
}
}
// 模板中使用
${toCamelCase('user_name')} // 输出: userName
2. 条件生成逻辑
<#-- 根据字段类型添加校验注解 -->
<#list table.fields as field>
<#if field.propertyType == "String">
@Size(max = 50, message = "${field.comment}长度不能超过50")
<#elseif field.propertyType == "Integer">
@Min(value = 0, message = "${field.comment}不能小于0")
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
3. 多文件输出
<#-- 生成DTO文件 -->
<#assign dtoPackage = package.Entity?replace(".entity", ".dto")>
package ${dtoPackage};
public class ${entity}DTO {
<#-- 只包含部分字段 -->
private String username;
private String email;
}
六、最佳实践与性能优化
1. 模板组织策略
resources/
└── templates/
├── entity/ # 实体模板
│ ├── base.ftl # 基础模板
│ └── ext.ftl # 扩展模板
├── mapper/ # Mapper模板
└── common/ # 公共片段
└── header.ftl
2. 模板片段复用
<#-- header.ftl -->
/**
* 生成时间: ${.now?string("yyyy-MM-dd HH:mm:ss")}
* 表名: ${table.name}
*/
<#-- entity.ftl -->
<#include "common/header.ftl">
package ${package.Entity};
public class ${entity} {
// ...
}
3. 模板预编译与缓存
// 生产环境启用模板缓存
Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
cfg.setTemplateUpdateDelayMilliseconds(3600000); // 1小时更新检查
// 使用模板缓存管理器
TemplateCacheManager cacheManager = new TemplateCacheManager();
cacheManager.setCacheStorage(new StrongCacheStorage());
generator.setTemplateEngine(new FreemarkerTemplateEngine(cfg, cacheManager));
4. 批量生成优化
// 分批次处理大表
List<String> tables = Arrays.asList("user", "order", "product");
int batchSize = 10;
for (int i = 0; i < tables.size(); i += batchSize) {
List<String> batch = tables.subList(i, Math.min(i + batchSize, tables.size()));
strategy.setInclude(batch.toArray(new String[0]));
generator.execute();
}
七、性能对比(Freemarker vs Velocity)
特性 |
Freemarker |
Velocity |
语法复杂度 |
★★★ (较复杂) |
★★ (简单) |
性能 |
★★★ (快) |
★★ (中等) |
错误处理 |
★★★ (详细错误信息) |
★★ (基本错误信息) |
模板继承 |
支持 |
不支持 |
宏定义 |
强大 |
有限 |
社区活跃度 |
★★★ (活跃) |
★★ (维护中) |
推荐场景 |
复杂模板、企业级应用 |
简单模板、快速开发 |
八、完整配置示例
public class AdvancedGenerator {
public static void main(String[] args) {
// 1. 全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
globalConfig.setAuthor("Generator");
globalConfig.setOpen(false);
globalConfig.setFileOverride(true);
globalConfig.setSwagger2(true);
globalConfig.setDateType(DateType.TIME_PACK);
// 2. 数据源配置
DataSourceConfig dataSource = new DataSourceConfig();
dataSource.setUrl("jdbc:mysql://localhost:3306/db?useSSL=false");
dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 3. 包配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.example.project");
packageConfig.setEntity("entity");
packageConfig.setMapper("mapper");
// 4. 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setInclude("user", "product");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("tbl_");
strategy.setEntitySerialVersionUID(true);
strategy.setEntityBuilderModel(true);
// 5. 自定义模板配置
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setEntity("templates/advanced-entity.java.ftl");
templateConfig.setMapper("templates/mapper.java.ftl");
templateConfig.setXml(null); // 不生成XML
// 6. 自定义注入配置
InjectionConfig injectionConfig = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>();
map.put("company", "Acme Corp");
this.setMap(map);
}
};
// 7. 配置模板引擎
Configuration freemarkerCfg = new Configuration(Configuration.VERSION_2_3_31);
freemarkerCfg.setDefaultEncoding("UTF-8");
freemarkerCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// 8. 构建生成器
AutoGenerator generator = new AutoGenerator();
generator.setGlobalConfig(globalConfig);
generator.setDataSource(dataSource);
generator.setPackageInfo(packageConfig);
generator.setStrategy(strategy);
generator.setTemplate(templateConfig);
generator.setCfg(injectionConfig);
generator.setTemplateEngine(new CustomFreemarkerEngine(freemarkerCfg));
// 9. 执行生成
generator.execute();
}
static class CustomFreemarkerEngine extends FreemarkerTemplateEngine {
public CustomFreemarkerEngine(Configuration configuration) {
super(configuration);
}
@Override
public void init(Configuration config) {
config.setSharedVariable("currentYear", new SimpleNumber(Year.now().getValue()));
}
}
}
总结
关键实践要点
- 模板分层:基础模板 + 业务模板组合使用
- 安全处理:对敏感字段特殊处理
- 性能优化:生产环境启用模板缓存
- 错误防御:模板中使用空值处理(!)
- 版本管理:模板纳入Git版本控制
选择建议
- 推荐 Freemarker:功能强大,适合复杂项目
- 简单项目用 Velocity:学习曲线平缓
- 避免混用:统一项目中的模板引擎
通过合理使用模板引擎,MyBatis-Plus代码生成效率可提升300%,同时保持代码风格一致性。建议将通用模板封装为公司级代码生成组件,实现架构统一管理。