添加依赖(旧版)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
代码(3.5.1之前, 旧版)
注意配置到测试模块, 因为最后不会进行打包.
public class CodeGet {
public static void main(String[] args) {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir("C:\\Users\\tarena\\zymall\\service\\model_vod"+"/src/main/java");
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setAuthor("liyunfei");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://101.35.121.103:32759/zy_vod");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root1234");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
// com.atguigu.ggkt.vod.
pc.setModuleName("model_vod"); //模块名
pc.setParent("com.zy");
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("teacher");
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
添加依赖(新版)
包括mybatis-plus-generator和默认的模板引擎velocity依赖的velocity-engine-core。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
代码生成配置(新版, 3.5.1之后)
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
/**
* This class is for xxxx.
*
* @author pdai
*/
public class TestGenCode {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/test_db?useSSL=false&autoReconnect=true&characterEncoding=utf8", "test", "bfXa4Pt2lUUScy8jakXf")
.globalConfig(builder ->
builder.author("pdai") // 设置作者
.enableSwagger() // 开启 swagger 模式
)
.packageConfig(builder ->
builder.parent("tech.pdai.springboot.mysql8.mybatisplus.anno") // 设置父包名
.moduleName("gencode") // 设置父包模块名
)
.strategyConfig(builder ->
builder.addInclude("tb_user", "tb_role", "tb_user_role")
)
.execute();
}
}
原理
配置的装载, FastAutoGenerator本质上就是通过builder注入各种配置,并将它交给代码生成主类:AutoGenerator
public void execute() {
new AutoGenerator(this.dataSourceConfigBuilder.build())
// 全局配置
.global(this.globalConfigBuilder.build())
// 包配置
.packageInfo(this.packageConfigBuilder.build())
// 策略配置
.strategy(this.strategyConfigBuilder.build())
// 注入配置
.injection(this.injectionConfigBuilder.build())
// 模板配置
.template(this.templateConfigBuilder.build())
// 执行
.execute(this.templateEngine);
}
AutoGenerator中execute方法,包括初始化配置和模板引擎(默认是Velocity),然后将配置交给模板引擎初始化执行文件输出
/**
* 生成代码
*
* @param templateEngine 模板引擎
*/
public void execute(AbstractTemplateEngine templateEngine) {
logger.debug("==========================准备生成文件...==========================");
// 初始化配置
if (null == config) {
config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig, injection);
}
if (null == templateEngine) {
// 为了兼容之前逻辑,采用 Velocity 引擎 【 默认 】
templateEngine = new VelocityTemplateEngine();
}
templateEngine.setConfigBuilder(config);
// 模板引擎初始化执行文件输出
templateEngine.init(config).batchOutput().open();
logger.debug("==========================文件生成完成!!!==========================");
}
模板引擎中batchOuput方法中,包含获取表的信息并根据模板来生成类文件。
/**
* 批量输出 java xml 文件
*/
@NotNull
public AbstractTemplateEngine batchOutput() {
try {
ConfigBuilder config = this.getConfigBuilder();
List<TableInfo> tableInfoList = config.getTableInfoList();
tableInfoList.forEach(tableInfo -> {
Map<String, Object> objectMap = this.getObjectMap(config, tableInfo);
Optional.ofNullable(config.getInjectionConfig()).ifPresent(t -> {
t.beforeOutputFile(tableInfo, objectMap);
// 输出自定义文件
outputCustomFile(t.getCustomFile(), tableInfo, objectMap);
});
// entity
outputEntity(tableInfo, objectMap);
// mapper and xml
outputMapper(tableInfo, objectMap);
// service
outputService(tableInfo, objectMap);
// controller
outputController(tableInfo, objectMap);
});
} catch (Exception e) {
throw new RuntimeException("无法创建文件,请检查配置信息!", e);
}
return this;
}
获取表的列表,由ConfigBuilder完成
public List<TableInfo> getTableInfoList() {
if (tableInfoList.isEmpty()) {
// TODO 暂时不开放自定义
List<TableInfo> tableInfos = new IDatabaseQuery.DefaultDatabaseQuery(this).queryTables();
if (!tableInfos.isEmpty()) {
this.tableInfoList.addAll(tableInfos);
}
}
return tableInfoList;
}
然后获取上述单个表(tableInfo)的具体信息(objectMap)
/**
* 渲染对象 MAP 信息
*
* @param config 配置信息
* @param tableInfo 表信息对象
* @return ignore
*/
@NotNull
public Map<String, Object> getObjectMap(@NotNull ConfigBuilder config, @NotNull TableInfo tableInfo) {
StrategyConfig strategyConfig = config.getStrategyConfig();
Map<String, Object> controllerData = strategyConfig.controller().renderData(tableInfo);
Map<String, Object> objectMap = new HashMap<>(controllerData);
Map<String, Object> mapperData = strategyConfig.mapper().renderData(tableInfo);
objectMap.putAll(mapperData);
Map<String, Object> serviceData = strategyConfig.service().renderData(tableInfo);
objectMap.putAll(serviceData);
Map<String, Object> entityData = strategyConfig.entity().renderData(tableInfo);
objectMap.putAll(entityData);
objectMap.put("config", config);
objectMap.put("package", config.getPackageConfig().getPackageInfo());
GlobalConfig globalConfig = config.getGlobalConfig();
objectMap.put("author", globalConfig.getAuthor());
objectMap.put("kotlin", globalConfig.isKotlin());
objectMap.put("swagger", globalConfig.isSwagger());
objectMap.put("date", globalConfig.getCommentDate());
// 启用 schema 处理逻辑
String schemaName = "";
if (strategyConfig.isEnableSchema()) {
// 存在 schemaName 设置拼接 . 组合表名
schemaName = config.getDataSourceConfig().getSchemaName();
if (StringUtils.isNotBlank(schemaName)) {
schemaName += ".";
tableInfo.setConvert(true);
}
}
objectMap.put("schemaName", schemaName);
objectMap.put("table", tableInfo);
objectMap.put("entity", tableInfo.getEntityName());
return objectMap;
}
根据TableInfo和objectMap输出类文件,以输出Entity实体类为例
/**
* 输出实体文件
*
* @param tableInfo 表信息
* @param objectMap 渲染数据
* @since 3.5.0
*/
protected void outputEntity(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
String entityName = tableInfo.getEntityName();
String entityPath = getPathInfo(OutputFile.entity);
if (StringUtils.isNotBlank(entityName) && StringUtils.isNotBlank(entityPath)) {
getTemplateFilePath(template -> template.getEntity(getConfigBuilder().getGlobalConfig().isKotlin())).ifPresent((entity) -> {
String entityFile = String.format((entityPath + File.separator + "%s" + suffixJavaOrKt()), entityName);
outputFile(new File(entityFile), objectMap, entity, getConfigBuilder().getStrategyConfig().entity().isFileOverride());
});
}
}
在outputFile中来确定生成文件的名字和路径
/**
* 输出文件
*
* @param file 文件
* @param objectMap 渲染信息
* @param templatePath 模板路径
* @param fileOverride 是否覆盖已有文件
* @since 3.5.2
*/
protected void outputFile(@NotNull File file, @NotNull Map<String, Object> objectMap, @NotNull String templatePath, boolean fileOverride) {
if (isCreate(file, fileOverride)) {
try {
// 全局判断【默认】
boolean exist = file.exists();
if (!exist) {
File parentFile = file.getParentFile();
FileUtils.forceMkdir(parentFile);
}
writer(objectMap, templatePath, file);
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
最后通过writer方法生成文件
/**
* 将模板转化成为文件
*
* @param objectMap 渲染对象 MAP 信息
* @param templatePath 模板文件
* @param outputFile 文件生成的目录
* @throws Exception 异常
* @since 3.5.0
*/
public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
this.writer(objectMap, templatePath, outputFile.getPath());
logger.debug("模板:" + templatePath + "; 文件:" + outputFile);
}
本质上就是调用模版引擎来生成.
如何看待MyBatis-Plus生成代码的功能?
简单而言,对于初学者好像能生成代码作用很大,实际情况是很鸡肋!
- 从上面的源码我们可以看出,生成类只适合单表结构,表的关联无法处理;
- 对于单表的CRUD类,如果可以自动化生成,必然是可以很好的抽象的,而BaseMapper, BaseServiceImpl的封装已经足够了;
- 通常真正可以通过一体化集成前端代码的生成,才有一定的意义;
- 当然少部分情况快速提供接口的可以考虑,不过其实也省不了什么时间。
本文由 liyunfei 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 8,2022