# Mybatis-Flex 代码生成器 在 mybatis-flex 的模块 `mybatis-flex-codegen` 中,提供了可以通过数据库表,生成 Entity 类和 Mapper 类的功能。当我们把数据库表设计完成 后可以使用其快速生成 Entity 和 Mapper 的 java 类。 在使用前先添加 `mybatis-flex-codegen` 的 Maven 依赖: ```xml com.mybatis-flex mybatis-flex-codegen 1.2.3 ``` 同时需要添加数据源的 Maven 依赖和 jdbc 驱动依赖: ```xml com.zaxxer HikariCP 4.0.3 mysql mysql-connector-java 8.0.32 ``` 然后,编写一个任意带有 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 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 tableConfigMap; //设置某个列的全局配置。 private Map defaultColumnConfigMap; //生成那些表,白名单。 private Set generateTables; //不生成那些表,黑名单。 private Set 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 insertListenerClass; private Class 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 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 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 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 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()); ```