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

12 KiB
Raw Blame History

Mybatis-Flex 代码生成器

在 mybatis-flex 的模块 mybatis-flex-codegen 中,提供了可以通过数据库表,生成 Entity 类和 Mapper 类的功能。当我们把数据库表设计完成 后可以使用其快速生成 Entity 和 Mapper 的 java 类。

在使用前先添加 mybatis-flex-codegen 的 Maven 依赖:

<dependency>
    <groupId>com.mybatis-flex</groupId>
    <artifactId>mybatis-flex-codegen</artifactId>
    <version>1.2.3</version>
</dependency>

同时需要添加数据源的 Maven 依赖和 jdbc 驱动依赖:

<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 方法的类,如下所示:

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 设置章节

使用介绍

在 Mybatis-Flex 的代码生成器中,支持如下 6 种类型的的产物生成:

  • Entity 实体类
  • Mapper 映射类
  • TableDef 表定义辅助类
  • Service 服务类
  • ServiceImpl 服务实现类
  • Controller 控制类

启用或关闭某种类型产物的生成,代码如下:


// 开启 Entity 的生成
globalConfig.enableEntity();
// 关闭 Entity 的生成
globalConfig.disableEntity();

所有方法均支持链式调用配置,代码如下:


// 设置生成 Entity 并启用 Lombok、设置父类
globalConfig.enableEntity()
        .setWithLombok(true)
        .setSupperClass(BaseEntity.class);

全局配置 GlobalConfig

GlobalConfig 全局配置项包含多个子配置项:


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 支持的配置如下:


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 支持的配置如下:


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 支持的配置如下:


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 支持的配置如下:


public class MapperConfig {

    //Mapper 类的前缀。
    private String classPrefix = "";

    //Mapper 类的后缀。
    private String classSuffix = "Mapper";

    //自定义 Mapper 的父类。
    private Class<?> supperClass = BaseMapper.class;

}

Service 生成配置 ServiceConfig

ServiceConfig 支持的配置如下:


public class ServiceConfig {

    //Service 类的前缀。
    private String classPrefix = "";

    //Service 类的后缀。
    private String classSuffix = "Service";

    //自定义 Service 的父类。
    private Class<?> supperClass = IService.class;

}

ServiceImpl 生成配置 ServiceImplConfig

ServiceImplConfig 支持的配置如下:


public class ServiceImplConfig {

    //ServiceImpl 类的前缀。
    private String classPrefix = "";

    //ServiceImpl 类的后缀。
    private String classSuffix = "ServiceImpl";

    //自定义 ServiceImpl 的父类。
    private Class<?> supperClass = ServiceImpl.class;

}

Controller 生成配置 ControllerConfig

ControllerConfig 支持的配置如下:


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 支持的配置如下:


public class TableDefConfig {

    //TableDef 类的前缀。
    private String classPrefix = "";

    //TableDef 类的后缀。
    private String classSuffix = "Def";

}

表配置 TableConfig

TableConfig 支持的配置如下:

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 支持的配置如下:

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 驱动的数据类型为自定义的 数据类型,在开始生成代码之前,可以先调用其进行配置,例如:

JdbcTypeMapping.registerMapping(LocalDateTime.class, Date.class);

那么,当我们生成代码的时候,发现 JDBC 驱动的数据类型为 LocalDateTime,则 Entity 对应的属性类型为 Date

自定义代码模板

通过 GlobalConfig(全局配置)的 setTemplateEngine() 方法,可以配置自己的模板引擎以及模板,以下是内置的 EnjoyTemplate 的代码示例:

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 实体类的代码如下:

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 接口,例如:

public class HtmlGenerator implements IGenerator {

    @Override
    public void generate(Table table, GlobalConfig globalConfig) {
        //在这里生成 html 代码
    }
}

最后,通过 GeneratorFactory 来注册 HtmlGenerator 即可:

GeneratorFactory.registerGenerator("html",new HtmlGenerator());