觉得 mp 代码生成器很神奇? 一文告诉你底层原理!

当我们在做后台开发时,会经常和数据库打交道,渐渐的也就衍生出了很多的持久层技术,从一开始源生的 JDBC ,到 HibernateJPA (全自动框架),再到后来的 MyBatisMyBatis-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 流程图

点我查看详情

Mp 代码生成器

2.2 配置生成策略

1.1 配置数据源

配置数据源

1.2 配置包

配置包

1.3 全局配置

全局配置

1.4 配置自定义策略

配置自定义策略

2.3 执行

2.3.1 ChangCode.java
配置并执行代码生成

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

见 2.3.4.2

通过 dbQuery.tableName() 获取表名
在这里插入图片描述

在这里插入图片描述

2.3.4.6 是否有需要反向生成或排除的表信息

在这里插入图片描述

2.3.5 写入文件

见 2.3.4
在这里插入图片描述

2.3.6 打开生成文件目录

见 2.3.3

在这里插入图片描述
在这里插入图片描述

3. 总结

代码生成器,主要就是用户自定义简单的代码生成策略, 然后, mp 底层通过 sql ='show table status where 1=1' 生成需要生成的表的信息,然后,根据数据库配置和表名,获取对应的表信息

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值