mybatis-plus 生成代码
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
1.导入依赖
导入最新版本的mybatis-plus-generator的maven依赖,因为要使用到数据库,所有也要导入mysql的包
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
2.生成代码
mp提供了两种生成方法。
- 快速生成
快速生成是将各种配置全部写在代码中,直接生成FastAutoGenerator.create("url", "username", "password") .globalConfig(builder -> { builder.author("baomidou") // 设置作者 .enableSwagger() // 开启 swagger 模式 .fileOverride() // 覆盖已生成文件 .outputDir("D://"); // 指定输出目录 }) .packageConfig(builder -> { builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名 .moduleName("system") // 设置父包模块名 .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径 }) .strategyConfig(builder -> { builder.addInclude("t_simple") // 设置需要生成的表名 .addTablePrefix("t_", "c_"); // 设置过滤表前缀 }) .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板 .execute();
交互式生成
交互式生成是一部分配置写在代码中,一部分配置可以手动输入进行配置FastAutoGenerator.create(DATA_SOURCE_CONFIG) // 全局配置 .globalConfig((scanner, builder) -> builder.author(scanner.apply("请输入作者名称?")).fileOverride()) // 包配置 .packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?"))) // 策略配置 .strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all"))) .controllerBuilder().enableRestStyle().enableHyphenStyle() .entityBuilder().enableLombok().addTableFills( new Column("create_time", FieldFill.INSERT) ).build()) /* 模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker .templateEngine(new BeetlTemplateEngine()) .templateEngine(new FreemarkerTemplateEngine()) */ .execute(); // 处理 all 情况 protected static List<String> getTables(String tables) { return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(",")); }
3.详细配置
本篇文章使用快速和交互式共存的方式进行代码的生成,把一些固定的配置使用快速配置,把需要手动切换的配置使用手动进行输入。
1. 数据库配置(DataSourceConfig)
先创建一个数据库配置文件在resources
下
db.yml
url: jdbc:mysql:///misv2?serverTimezone=GMT%2B8
username: root
password: root
然后在main方法中进行加载配置文件
Properties properties = new Properties();
InputStream in = ClassLoader.getSystemResourceAsStream("db.yml");
try {
properties.load(in);
} catch (IOException e) {
log.error("配置文件不存在");
throw new RuntimeException(e);
}
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
我们看到FastAutoGenerator.cteate方法需要的一个参数是DataSourceConfig.Builder
我们使用该内部类中的一个构造方法
DataSourceConfig.Builder dataSourceConfig = new DataSourceConfig.Builder(url, username, password);
然后将该dataSourceConfig传入
2. 全局配置(GlobalConfig)
接下来进行全局配置
注意下这个过时了
这些内容我们不需要手动输入,就直接写在代码中
// 全局配置
.globalConfig((builder) -> builder.author("coco")
//禁止打开输出目录
.disableOpenDir()
//输出目录
.outputDir(System.getProperty("user.dir") + "\\module\\generator\\src\\main\\java\\top\\wangqi\\")
//开启springdoc 如果自己使用的是swagger 就用.enableSwagger
.enableSpringdoc()
//注释时间
.commentDate("yyyy-MM-dd")
//时间策略
.dateType(DateType.TIME_PACK))
具体的时间类型在这
3. 包配置(PackageConfig)
这里我们也不需要手动配置,就直接写在代码中,方法可能不全,自己探索
// 包配置
.packageConfig((builder) -> builder
//就是你src/java之后到你启动类那一层
.parent("com\\zzw\\mis\\")
//父包模块名
.moduleName("mis-module-generator")
//entity包名
.entity("entity")
//service包名
.service("service")
//service实现类包名
.serviceImpl("service.impl")
//控制器包名
.controller("controller")
//Mapper 包名
.mapper("dao")
//Mapper XML 包名
.xml("mapper")
//路径配置信息 Collections.singletonMap(OutputFile.mapperXml, "D://")
// .pathInfo()
//子包名 这块貌似是在包路径上再拼上一个路径
//.joinPackage("")
)
4. 模板配置(TemplateConfig)
//模板配置
.templateConfig((builder -> builder
//设置 controller 模板路径
.controller("/templates/controller.ftl")
//设置实体模板路径(JAVA)
.entity("/templates/entity.ftl")
//设置 service 模板路径
.service("/templates/service.ftl")
//设置 serviceImpl 模板路径
.serviceImpl("/templates/serviceImpl.ftl")
//设置 mapper 模板路径
.mapper("/templates/mapper.ftl")
//设置 mapperXml 模板路径
.xml("/templates/mapper.xml.ftl")))
如果不限于内置的模板的话可以自己进行修改,传入模板的地址
内置模板在这里
5. 注入配置(InjectionConfig)
Map<String, String> customFileMap = new HashMap<>(3);
customFileMap.put("Vo.java", "/templates/vo.ftl");
customFileMap.put("Query.java", "/templates/query.ftl");
customFileMap.put("Convert.java", "/templates/convert.ftl");
Map<String, Object> propMap = new HashMap<>(1);
propMap.put("superQueryClass", true);
//注入配置
.injectionConfig(builder -> builder
//自定义属性
.customMap(propMap)
//自定义配置模板文件
.customFile(customFileMap))
6. 策略配置(StrategyConfig)
// 策略配置
.strategyConfig((scanner, builder) -> builder
//表字段前缀
.addTablePrefix("buss_")
//输入需要生成的表
.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
//controller配置
.controllerBuilder()
//开启rest风格
.enableRestStyle()
//开启驼峰转连字符
.enableHyphenStyle()
//实体配置
.entityBuilder()
//开启lombok
.enableLombok()
//设置父类
.superClass("com.zzw.mis.framework.mybatis.entity.BaseEntity")
//乐观锁数据库字段名
.versionColumnName("version")
//乐观锁实体字段名
.versionPropertyName("version")
//逻辑删除字段数据库字段
.logicDeleteColumnName("deleted")
//逻辑删除实体字段
.logicDeletePropertyName("deleted")
//格式化文件名
.formatFileName("%sEntity")
//添加父类的字段
.addSuperEntityColumns("id", "version", "deleted", "creator", "create_time", "updater", "update_time")
//字段填充
.addTableFills(new Column("create_time", FieldFill.INSERT))
//主键策略
.idType(IdType.ASSIGN_UUID)
//service配置
.serviceBuilder()
//service接口父类
.superServiceClass("com.zzw.mis.framework.mybatis.service.BaseService")
//service实现类父类
.superServiceImplClass("com.zzw.mis.framework.mybatis.service.impl.BaseServiceImpl")
//mapper配置
.mapperBuilder()
//父类
.superClass("com.zzw.mis.framework.mybatis.dao.BaseDao")
//设置mapper注解
.mapperAnnotation(Mapper.class)
//启用 BaseResultMap 生成
.enableBaseResultMap()
.build())
7. 模板引擎配置
.templateEngine(new FreemarkerTemplateEngine())
TestTemplateEngine.java 模板引擎配置代码 这是我主要是配置自定义的vo和query等自定义文件的生成
package com.zzw.mis;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import java.util.Map;
/**
* <p>项目名称: zzw-tech </p>
* <p>包名称: com.zzw.mis </p>
* <p>描述: </p>
* <p> </p>
* <p>创建时间: 2022/12/1 17 </p>
*
* @author coco
* @version v1.0
*/
public class TestTemplateEngine extends FreemarkerTemplateEngine {
@Override
protected void outputCustomFile (@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
String name = tableInfo.getName();
int i = name.indexOf("_");
String substring1 = name.substring(i + 1);
String tableName = NamingStrategy.underlineToCamel(substring1);
String substring = tableName.substring(0, 1).toUpperCase();
tableName = substring + tableName.substring(1);
String parentPath = getPathInfo(OutputFile.parent);
String finalTableName = tableName;
objectMap.put("tableName", finalTableName);
customFiles.forEach(file -> {
String[] split = file.getTemplatePath().split("/");
String s = split[split.length - 1];
String[] split1 = s.split("\\.");
String dir = split1[0];
String filePath = StringUtils.isNotBlank(file.getFilePath()) ? file.getFilePath() : parentPath + File.separator + dir;
if (StringUtils.isNotBlank(file.getPackageName())) {
filePath = filePath + File.separator + dir + file.getPackageName();
}
String fileName = filePath + File.separator + finalTableName + file.getFileName();
outputFile(new File(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
});
}
}
8. 接下来就完了 生成代码 踩坑改bug
哦豁,启动报错了
找不到freemaker文件,我们加入依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
继续报错
找不到我定义的那几个文件
找来找去原来是自定义文件位置放错了,要放在resources下
然后启动
哦豁 继续报错
还是找不到文件,但是这次是没找到mapper.ftl.ftl,但是我明明写的是mapper.ftl啊,所以,freemarker中查找视图是不需要添加后缀的,我们去掉
继续运行,还是有问题
这里主要是没有设置mapper xml文件的位置和总体文件的位置问题
我们在package 配置中加入
.pathInfo(Collections.singletonMap(OutputFile.xml, dir + "\mis-cloud-module\mis-module-generator\src\main\resources\mapper"))
我们这两边都加了,所以去掉一边
然后启动
成功,但是对我来说还有一些小瑕疵,我在查看entity的时候,发现数据库的bit类型返回到后端代码也是Byte
我们的需求是boolean
继续修改
9. 修改数据库类型与实体类型的对应
当我去修改的时候才发现,是我数据库的问题
mybatis-plus中的类型转换是当数据库字段为bit(1)和tinyint(1)时才会转换为boolean,而我的没写长度,于是乎给我转换为Byte了。这波大意了啊!
最后,我们的代码就成功生成,暂时没发现什么问题。上全部代码
代码结构
pom.xml
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mis-cloud-module</artifactId>
<groupId>com.zzw.mis</groupId>
<version>2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mis-module-generator</artifactId>
<packaging>jar</packaging>
<name>mis-module-generator</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.zzw.mis</groupId>
<artifactId>mis-cloud-mybatis</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
</dependency>
</dependencies>
</project>
db.yml
url: jdbc:mysql:///bigdata?serverTimezone=GMT%2B8
username: root
password: root
module: mis-cloud-module/mis-module-generator
parent: com.zzw.mis
App.java
package com.zzw.mis;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.fill.Column;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* Hello world!
*/
@Slf4j
public class App {
public static void main (String[] args) {
Properties properties = new Properties();
InputStream in = ClassLoader.getSystemResourceAsStream("db.yml");
try {
properties.load(in);
} catch (IOException e) {
log.error("配置文件不存在");
throw new RuntimeException(e);
}
String dir = System.getProperty("user.dir");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
String module = properties.getProperty("module");
String parent = properties.getProperty("parent");
DataSourceConfig.Builder dataSourceConfig = new DataSourceConfig.Builder(url, username, password);
dataSourceConfig.typeConvert(new MySqlTypeConvert());
Map<String, String> customFileMap = new HashMap<>(3);
customFileMap.put("Vo.java", "templates/vo.ftl");
customFileMap.put("Query.java", "templates/query.ftl");
customFileMap.put("Convert.java", "templates/convert.ftl");
Map<String, Object> propMap = new HashMap<>();
propMap.put("superQueryClass", "BaseQuery");
propMap.put("queryDir", "query");
propMap.put("voDir", "vo");
propMap.put("convertDir", "convert");
FastAutoGenerator.create(dataSourceConfig)
// 全局配置
.globalConfig((builder) -> builder.author("coco")
//禁止打开输出目录
.disableOpenDir()
//输出目录
.outputDir(dir + "\\" + module + "\\src\\main\\java")
//开启springdoc 如果自己使用的是swagger 就用.enableSwagger
.enableSpringdoc()
//注释时间
.commentDate("yyyy-MM-dd")
//时间策略
.dateType(DateType.TIME_PACK))
// 包配置
.packageConfig((builder) -> builder
//就是你src/java之后到你启动类那一层
.parent(parent)
//父包模块名
// .moduleName("mis-module-generator")
//entity包名
.entity("entity")
//service包名
.service("service")
//service实现类包名
.serviceImpl("service.impl")
//控制器包名
.controller("controller")
//Mapper 包名
.mapper("dao")
//Mapper XML 包名
//xml文件输出位置
.pathInfo(Collections.singletonMap(OutputFile.xml, dir + "\\" + module + "\\src\\main\\resources\\mapper"))
//路径配置信息 Collections.singletonMap(OutputFile.mapperXml, "D://")
// .pathInfo()
//子包名 这块貌似是在包路径上再拼上一个路径
//.joinPackage("")
)
//模板配置
.templateConfig((builder -> builder
//设置 controller 模板路径
.controller("templates/controller")
//设置实体模板路径(JAVA)
.entity("templates/entity")
//设置 service 模板路径
.service("templates/service")
//设置 serviceImpl 模板路径
.serviceImpl("templates/serviceImpl")
//设置 mapper 模板路径
.mapper("templates/mapper")
//设置 mapperXml 模板路径
.xml("templates/mapper.xml")))
//注入配置
.injectionConfig(builder -> builder
//自定义属性
.customMap(propMap)
//自定义配置模板文件
.customFile(customFileMap))
// 策略配置
.strategyConfig((scanner, builder) -> builder
//表字段前缀
.addTablePrefix("buss_")
//输入需要生成的表
.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
//controller配置
.controllerBuilder()
//开启rest风格
.enableRestStyle()
//开启驼峰转连字符
.enableHyphenStyle()
//实体配置
.entityBuilder()
//开启lombok
.enableLombok()
//设置父类
.superClass("com.zzw.mis.framework.mybatis.entity.BaseEntity")
//乐观锁数据库字段名
.versionColumnName("version")
//乐观锁实体字段名
.versionPropertyName("version")
//逻辑删除字段数据库字段
.logicDeleteColumnName("deleted")
//逻辑删除实体字段
.logicDeletePropertyName("deleted")
//格式化文件名
.formatFileName("%sEntity")
//添加父类的字段
.addSuperEntityColumns("id", "version", "deleted", "creator", "create_time", "updater", "update_time")
//字段填充
.addTableFills(new Column("create_time", FieldFill.INSERT))
//主键策略
.idType(IdType.ASSIGN_UUID)
//service配置
.serviceBuilder()
//service接口父类
.superServiceClass("com.zzw.mis.framework.mybatis.service.BaseService")
//service实现类父类
.superServiceImplClass("com.zzw.mis.framework.mybatis.service.impl.BaseServiceImpl")
//service文件命名
.formatServiceFileName("%sService")
//mapper配置
.mapperBuilder()
//父类
.superClass("com.zzw.mis.framework.mybatis.dao.BaseDao")
//设置mapper注解
.mapperAnnotation(Mapper.class)
//启用 BaseResultMap 生成
.enableBaseResultMap().build()).templateEngine(new TestTemplateEngine())
/*
模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
.templateEngine(new BeetlTemplateEngine())
*/.execute();
// System.out.println(System.getProperty("user.dir") + "\\mis-cloud-module\\mis-module-generator\\src\\main\\java\\com\\zzw\\mis\\");
}
// 处理 all 情况
protected static List<String> getTables (String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}
TestTemplateEngine.java
package com.zzw.mis;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import java.util.Map;
/**
* <p>项目名称: zzw-tech </p>
* <p>包名称: com.zzw.mis </p>
* <p>描述: </p>
* <p> </p>
* <p>创建时间: 2022/12/1 17 </p>
*
* @author coco
* @version v1.0
*/
public class TestTemplateEngine extends FreemarkerTemplateEngine {
@Override
protected void outputCustomFile (@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
String name = tableInfo.getName();
int i = name.indexOf("_");
String substring1 = name.substring(i + 1);
String tableName = NamingStrategy.underlineToCamel(substring1);
String substring = tableName.substring(0, 1).toUpperCase();
tableName = substring + tableName.substring(1);
String parentPath = getPathInfo(OutputFile.parent);
String finalTableName = tableName;
objectMap.put("tableName", finalTableName);
customFiles.forEach(file -> {
String[] split = file.getTemplatePath().split("/");
String s = split[split.length - 1];
String[] split1 = s.split("\\.");
String dir = split1[0];
String filePath = StringUtils.isNotBlank(file.getFilePath()) ? file.getFilePath() : parentPath + File.separator + dir;
if (StringUtils.isNotBlank(file.getPackageName())) {
filePath = filePath + File.separator + dir + file.getPackageName();
}
String fileName = filePath + File.separator + finalTableName + file.getFileName();
outputFile(new File(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
});
}
}
4.结尾
到这里了,就点个赞吧,如果觉得可以分享好友收藏网站下次再来看。
- 本文标签: Spring Boot
- 本文链接: https://blog.wangqi2020.top/article/51
- 版权声明: 本文由王祁原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权