mybatis-flex/docs/zh/others/codegen.md
2023-05-15 19:45:48 +08:00

516 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Mybatis-Flex 代码生成器
在 mybatis-flex 的模块 `mybatis-flex-codegen` 中,提供了可以通过数据库表,生成 Entity 类和 Mapper 类的功能。当我们把数据库表设计完成
后可以使用其快速生成 Entity 和 Mapper 的 java 类。
在使用前先添加 `mybatis-flex-codegen` 的 Maven 依赖:
```xml
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.2.3</version>
</dependency>
```
同时需要添加数据源的 Maven 依赖和 jdbc 驱动依赖:
```xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
```
然后,编写一个任意带有 main 方法的类,如下所示:
```java
public class Codegen {
public static void main(String[] args) {
//配置数据源
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/your-database?characterEncoding=utf-8");
dataSource.setUsername("root");
dataSource.setPassword("******");
//创建配置内容
GlobalConfig globalConfig = new GlobalConfig();
//设置根包
globalConfig.getPackageConfig()
.setBasePackage("com.test");
//设置表前缀和只生成哪些表
globalConfig.getStrategyConfig()
.setTablePrefix("tb_")
.addGenerateTable("account", "account_session");
//设置生成 entity 并启用 Lombok
globalConfig.enableEntity()
.setWithLombok(true);
//设置生成 mapper
globalConfig.enableMapper();
//可以单独配置某个列
ColumnConfig columnConfig = new ColumnConfig();
columnConfig.setColumnName("tenant_id");
columnConfig.setLarge(true);
columnConfig.setVersion(true);
globalConfig.getStrategyConfig()
.addColumnConfig("account", columnConfig);
//通过 datasource 和 globalConfig 创建代码生成器
Generator generator = new Generator(dataSource, globalConfig);
//生成代码
generator.generate();
}
}
```
注意:由于 MyBatis-Flex 的 APT 功能会自动帮我们生成了 Mapper 的 Java 类,如果我们在代码生成器中选择生成 Mapper
则建议把 APT 的 Mapper 生成功能给关闭掉,否则系统中会存在两份一样功能的 Mapper。
关闭 APT 的 Mapper 类文件生成,请参考:[APT 设置章节](../others/apt.md)
## 使用介绍
在 Mybatis-Flex 的代码生成器中,支持如下 6 种类型的的产物生成:
- Entity 实体类
- Mapper 映射类
- TableDef 表定义辅助类
- Service 服务类
- ServiceImpl 服务实现类
- Controller 控制类
启用或关闭某种类型产物的生成,代码如下:
```java
// 开启 Entity 的生成
globalConfig.enableEntity();
// 关闭 Entity 的生成
globalConfig.disableEntity();
```
所有方法均支持链式调用配置,代码如下:
```java
// 设置生成 Entity 并启用 Lombok、设置父类
globalConfig.enableEntity()
.setWithLombok(true)
.setSupperClass(BaseEntity.class);
```
## 全局配置 `GlobalConfig`
GlobalConfig 全局配置项包含多个子配置项:
```java
public class GlobalConfig {
private final PackageConfig packageConfig;
private final StrategyConfig strategyConfig;
private EntityConfig entityConfig;
private MapperConfig mapperConfig;
private ServiceConfig serviceConfig;
private ServiceImplConfig serviceImplConfig;
private ControllerConfig controllerConfig;
private TableDefConfig tableDefConfig;
private Map<String, Object> customConfig;
}
```
## 包配置 `PackageConfig`
PackageConfig 支持的配置如下:
```java
public class PackageConfig {
//代码生成目录。
private String sourceDir;
//根包。
private String basePackage = "com.mybatisflex";
//Entity 所在包。
private String entityPackage;
//Mapper 所在包。
private String mapperPackage;
//Service 所在包。
private String servicePackage;
//ServiceImpl 所在包。
private String serviceImplPackage;
//Controller 所在包。
private String controllerPackage;
//TableDef 所在包。
private String tableDefPackage;
}
```
## 策略配置 `StrategyConfig`
StrategyConfig 支持的配置如下:
```java
public class StrategyConfig {
//数据库表前缀,多个前缀用英文逗号(, 隔开。
private String tablePrefix;
//逻辑删除的默认字段名称。
private String logicDeleteColumn;
//乐观锁的字段名称。
private String versionColumn;
//是否生成视图映射。
private boolean generateForView;
//是否覆盖之前生成的文件。
private boolean overwriteEnable;
//单独为某张表添加独立的配置。
private Map<String, TableConfig> tableConfigMap;
//设置某个列的全局配置。
private Map<String, ColumnConfig> defaultColumnConfigMap;
//生成那些表,白名单。
private Set<String> generateTables;
//不生成那些表,黑名单。
private Set<String> unGenerateTables;
//使用哪个模板引擎来生成代码。
protected ITemplate templateEngine;
}
```
## Entity 生成配置 `EntityConfig`
EntityConfig 支持的配置如下:
```java
public class EntityConfig {
//Entity 类的前缀。
private String classPrefix = "";
//Entity 类的后缀。
private String classSuffix = "";
//Entity 类的父类,可以自定义一些 BaseEntity 类。
private Class<?> supperClass;
//Entity 默认实现的接口。
private Class<?>[] implInterfaces = {Serializable.class};
//Entity 是否使用 Lombok 注解。
private boolean withLombok;
}
```
## Mapper 生成配置 `MapperConfig`
MapperConfig 支持的配置如下:
```java
public class MapperConfig {
//Mapper 类的前缀。
private String classPrefix = "";
//Mapper 类的后缀。
private String classSuffix = "Mapper";
//自定义 Mapper 的父类。
private Class<?> supperClass = BaseMapper.class;
}
```
## Service 生成配置 `ServiceConfig`
ServiceConfig 支持的配置如下:
```java
public class ServiceConfig {
//Service 类的前缀。
private String classPrefix = "";
//Service 类的后缀。
private String classSuffix = "Service";
//自定义 Service 的父类。
private Class<?> supperClass = IService.class;
}
```
## ServiceImpl 生成配置 `ServiceImplConfig`
ServiceImplConfig 支持的配置如下:
```java
public class ServiceImplConfig {
//ServiceImpl 类的前缀。
private String classPrefix = "";
//ServiceImpl 类的后缀。
private String classSuffix = "ServiceImpl";
//自定义 ServiceImpl 的父类。
private Class<?> supperClass = ServiceImpl.class;
}
```
## Controller 生成配置 `ControllerConfig`
ControllerConfig 支持的配置如下:
```java
public class ControllerConfig {
//Controller 类的前缀。
private String classPrefix = "";
//Controller 类的后缀。
private String classSuffix = "Controller";
//自定义 Controller 的父类。
private Class<?> supperClass;
//生成 REST 风格的 Controller。
private boolean restStyle = true;
}
```
## TableDef 生成配置 `TableDefConfig`
TableDefConfig 支持的配置如下:
```java
public class TableDefConfig {
//TableDef 类的前缀。
private String classPrefix = "";
//TableDef 类的后缀。
private String classSuffix = "Def";
}
```
## 表配置 `TableConfig`
TableConfig 支持的配置如下:
```java
public class TableConfig {
private String tableName;
/**
* 数据库的 schema
*/
private String schema;
/**
* 默认为 驼峰属性 转换为 下划线字段
*/
private Boolean camelToUnderline;
private Class<? extends InsertListener> insertListenerClass;
private Class<? extends UpdateListener> updateListenerClass;
// 是否启用ATP生成Mapper
private Boolean mapperGenerateEnable = Boolean.TRUE;
}
```
## 列配置 `ColumnConfig`
ColumnConfig 支持的配置如下:
```java
public class ColumnConfig implements Serializable {
private String onInsertValue;
private String onUpdateValue;
private Boolean isLarge;
private Boolean isLogicDelete;
private Boolean version;
private JdbcType jdbcType;
private Class<? extends TypeHandler> typeHandler;
private String mask;
private boolean isPrimaryKey = false;
private KeyType keyType;
private String keyValue;
private Boolean keyBefore;
// 是否是租户列
private Boolean tenantId;
}
```
## 自定义属性类型
Mybatis-Flex 内置了一个名为:`JdbcTypeMapping` 的 java 类,我们可以用其配置映射 Jdbc 驱动的数据类型为自定义的
数据类型,在开始生成代码之前,可以先调用其进行配置,例如:
```java
JdbcTypeMapping.registerMapping(LocalDateTime.class, Date.class);
```
那么,当我们生成代码的时候,发现 JDBC 驱动的数据类型为 `LocalDateTime`,则 Entity 对应的属性类型为 `Date`
## 自定义代码模板
通过 `GlobalConfig`(全局配置)的 `setTemplateEngine()` 方法,可以配置自己的模板引擎以及模板,以下是内置的 `EnjoyTemplate` 的代码示例:
```java
public class EnjoyTemplate implements ITemplate {
private Engine engine;
public EnjoyTemplate() {
engine = Engine.create("mybatis-flex", engine -> {
engine.setToClassPathSourceFactory();
engine.addSharedMethod(StringUtil.class);
});
Engine.addFieldGetterToFirst(new FieldGetters.IsMethodFieldGetter());
}
/**
* 生成 entity 的方法实现
*/
@Override
public void generateEntity(GlobalConfig globalConfig, Table table, File entityJavaFile) throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("globalConfig", globalConfig);
params.put("table", table);
FileOutputStream fileOutputStream = new FileOutputStream(entityJavaFile);
engine.getTemplate("/templates/enjoy/entity.tpl").render(params, fileOutputStream);
}
/**
* 生成 mapper 的方法实现
*/
@Override
public void generateMapper(GlobalConfig globalConfig, Table table, File mapperJavaFile) throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("globalConfig", globalConfig);
params.put("table", table);
FileOutputStream fileOutputStream = new FileOutputStream(mapperJavaFile);
engine.getTemplate("/templates/enjoy/mapper.tpl").render(params, fileOutputStream);
}
}
```
## 添加其他产物的生成
通过实现 `IGenerator` 来实现,比如 Entity 实体类的代码如下:
```java
public class EntityGenerator implements IGenerator {
private String templatePath = "/templates/enjoy/entity.tpl";
@Override
public void generate(Table table, GlobalConfig globalConfig) {
if (!globalConfig.isEntityGenerateEnable()) {
return;
}
PackageConfig packageConfig = globalConfig.getPackageConfig();
StrategyConfig strategyConfig = globalConfig.getStrategyConfig();
String entityPackagePath = packageConfig.getEntityPackage().replace(".", "/");
File entityJavaFile = new File(packageConfig.getSourceDir(), entityPackagePath + "/" +
table.buildEntityClassName() + ".java");
if (entityJavaFile.exists() && !strategyConfig.isOverwriteEnable()) {
return;
}
Map<String, Object> params = new HashMap<>(3);
params.put("table", table);
params.put("packageConfig", packageConfig);
params.put("entityConfig", globalConfig.getEntityConfig());
strategyConfig.getTemplateEngine().generate(params, templatePath, entityJavaFile);
}
}
```
如果我们想生成其他产物,比如 `html` ,可以通过编写自己的类,来实现 IGenerator 接口,例如:
```java
public class HtmlGenerator implements IGenerator {
@Override
public void generate(Table table, GlobalConfig globalConfig) {
//在这里生成 html 代码
}
}
```
最后,通过 `GeneratorFactory` 来注册 `HtmlGenerator` 即可:
```java
GeneratorFactory.registerGenerator("html",new HtmlGenerator());
```