文章目录
当我们在做后台开发时,会经常和数据库打交道,渐渐的也就衍生出了很多的持久层技术,从一开始源生的 JDBC
,到 Hibernate
和 JPA
(全自动框架),再到后来的 MyBatis
, MyBatis-plus
,随着技术的迭代,也使我们的开发变得越来越容易,简单。为了减少重复性的操作,渐渐也就出现了很多根据数据库表生成实体类的 代码生成插件
(eg.MyBatisX、MyBatisCodeHelperPro....
)和 代码生成器
。
那么代码生成器的原理是怎样的呢?为啥子根据简单的几个配置就可以生成需要的类呢?
首先我们先简单配置一下 mp
1. Mp 简单引入
1.1 引入 jar 炸药包
<dependencies>
<!-- mybatis-plus -->
<!-- mybatis-plus 是自己开发,并非官方的! -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--代码自动生成器依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
1.2 配置 .yml
# 数据库连接池给 spring 管理
spring:
# 配置数据源
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/java_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: xiaonuo123..
hikari:
# 自动提交
auto-commit: true
# 空闲连接超时时长
idle-timeout: 60000
# 连接超时时长
connection-timeout: 60000
# 最大生命周期, 0不过期
max-lifetime: 0
# 最小空闲连接数
minimum-idle: 10
# 最大连接数量
maximum-pool-size: 10
# mp
mybatis-plus:
mapper-locations: classpath*:com/nuo/javademo/mapper/xml/*Mapper.xml
# 配置逻辑删除
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
1.3 配置 config
@Configuration
// 扫描我们的 mapper 文件夹
@MapperScan("com.nuo.javademo.mapper")
// 开启事务管理
@EnableTransactionManagement
public class MyBatisPlusConfig {
// 引入插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
1.4 配置 EntityBase.java
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class EntityBase implements Serializable {
@ApiModelProperty(value = "主键", example = "1", required = true)
@JsonFormat(shape = JsonFormat.Shape.STRING)
@TableId(type = IdType.AUTO)
@TableField("id")
protected Long id;
/**
* 创建时间
*/
@ApiModelProperty(value = "创建时间 yyyy-MM-dd HH:mm:ss", example = "2020-11-28 00:12:23", required = true)
@JsonFormat(timezone = "GMT+8", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(value = "gmt_create")
private LocalDateTime gmtCreate;
/**
* 修改时间
*/
@ApiModelProperty(value = "修改时间 yyyy-MM-dd HH:mm:ss", example = "2020-11-28 00:12:23", required = true)
@JsonFormat(timezone = "GMT+8", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(value = "gmt_modified")
private LocalDateTime gmtModified;
/**
* 是否已删除
* 0:未删除
* 1:已删除
*/
@TableLogic
@JsonIgnore
@TableField(value = "is_delete")
private Integer isDelete;
// /**
// * 乐观锁
// */
// @Version
// private Integer version;
}
1.5 代码生成器
/**
* @author chang
* @description: TODO 代码自动生成器
*/
public class ChangCode {
public static final String PARENT = "com.nuo.javademo";
private static final String URL = "jdbc:mysql://localhost:3306/java_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true";
private static final String USERNAME = "root";
private static final String PASSWORD = "xiaonuo123..";
private static final String AUTHOR = "nuo";
public static void main(String[] args) {
//创建DataSource中的内部类Builder,进行数据库配置
FastAutoGenerator.create(new DataSourceConfig
//默认数据库为Mysql数据库
.Builder(URL, USERNAME, PASSWORD)
.typeConvert(new MySqlTypeConvert())
)
// 包配置
.packageConfig(t -> {
//已经默认设置包名为mapper,service,entity
t.parent(PARENT);
//设置当前的工程名
//t.moduleName("javademo");
})
// 全局配置
.globalConfig(t -> {
t.author(AUTHOR);
//开启 swagger 模式
t.enableSwagger();
//获取当前工程路径+目标目录(默认不覆盖生成文件)
t.outputDir(System.getProperty("user.dir") + "/src/main/java");
// 设置生成 Entity 对应 MySQL 中的日期策略
t.dateType(DateType.ONLY_DATE);
})
// 自定义策略配置
.strategyConfig(t -> {
//entityBuilder 设置 entity
// 设置要映射的表名
t.addInclude();
//自动链式和lombok
t.entityBuilder().enableChainModel();
t.entityBuilder().enableLombok();
//乐观锁
t.entityBuilder().versionColumnName("version");
//设置数据库 字段 映射到实体的命名规则为驼峰命名
t.entityBuilder().columnNaming(NamingStrategy.underline_to_camel);
//设置数据库 表 映射到实体的命名规则为驼峰命名
t.entityBuilder().naming(NamingStrategy.underline_to_camel);
//配置entity的父类
t.entityBuilder().superClass(EntityBase.class);
//controllerBuilder 配置controller
t.controllerBuilder().enableRestStyle();
//开启驼峰命名
t.controllerBuilder().enableHyphenStyle();
//格式化Service实现类文件名称
t.serviceBuilder().formatServiceFileName("%sService");
t.serviceBuilder().formatServiceImplFileName("%sServiceImpl");
}).execute();
}
}
接下来我们一起来浅瞅瞅 mp 代码生成器的原理和执行流程
2. Mp 代码生成器原理分析
2.1 流程图
2.2 配置生成策略
1.1 配置数据源
1.2 配置包
1.3 全局配置
1.4 配置自定义策略
2.3 执行
2.3.1 ChangCode.java
配置并执行代码生成
2.3.2 FastAutoGenerator.java
注入配置,执行代码生成器
2.3.3 AutoGenerator.java
1. 初始化配置
2. 设置生成器的模板引擎 (没自定义则使用 默认的 `Velocity` 引擎)
3. 初始化模板引擎
4. 执行 batchOutput() ,批量输出 java xml 文件
2.3.4 AbstractTemplateEngine.java
输出文件
2.3.4.0 关于获取表单信息
2.3.4.1 ConfigBuilder.java
2.3.4.2 IDatabaseQuery.java
查询
2.3.4.3 DecoratorDbQuery.java
查询表信息集
2.3.4.4 DecoratorDbQuery.java
获取查询 sql -> show table status where 1=1
2.3.4.5 拿到的表单信息集
2.3.4.6 add ()进 list
通过 dbQuery.tableName() 获取表名
2.3.4.6 是否有需要反向生成或排除的表信息
2.3.5 写入文件
2.3.6 打开生成文件目录
3. 总结
代码生成器,主要就是用户自定义简单的代码生成策略, 然后, mp 底层通过 sql ='show table status where 1=1' 生成需要生成的表的信息,然后,根据数据库配置和表名,获取对应的表信息