瀏覽代碼

代码生成器重构完成,合并回主干

hubin 2 年之前
父節點
當前提交
c39b6fc68d
共有 100 個文件被更改,包括 12050 次插入2 次删除
  1. 8 1
      build.gradle
  2. 二進制
      libs/DmJdbcDriver-1.7.0.jar
  3. 二進制
      libs/ojdbc8.jar
  4. 1 1
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/LambdaQueryChainWrapper.java
  5. 19 0
      mybatis-plus-generator/build.gradle
  6. 221 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/AutoGenerator.java
  7. 231 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/FastAutoGenerator.java
  8. 35 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/IFill.java
  9. 34 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/ITemplate.java
  10. 90 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ConstVal.java
  11. 470 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/DataSourceConfig.java
  12. 240 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/GlobalConfig.java
  13. 11 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IConfigBuilder.java
  14. 81 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IDbQuery.java
  15. 67 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IKeyWordsHandler.java
  16. 96 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/INameConvert.java
  17. 51 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ITypeConvert.java
  18. 196 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/InjectionConfig.java
  19. 37 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/OutputFile.java
  20. 322 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/PackageConfig.java
  21. 556 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/StrategyConfig.java
  22. 308 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateConfig.java
  23. 28 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateType.java
  24. 62 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/BaseBuilder.java
  25. 189 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/ConfigBuilder.java
  26. 216 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Controller.java
  27. 114 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/CustomFile.java
  28. 657 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Entity.java
  29. 117 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/GeneratorBuilder.java
  30. 328 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Mapper.java
  31. 110 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/PathInfoHandler.java
  32. 231 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Service.java
  33. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/package-info.java
  34. 87 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/ClickHouseTypeConvert.java
  35. 56 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DB2TypeConvert.java
  36. 82 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DmTypeConvert.java
  37. 89 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/FirebirdTypeConvert.java
  38. 89 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/KingbaseESTypeConvert.java
  39. 94 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/MySqlTypeConvert.java
  40. 96 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OracleTypeConvert.java
  41. 89 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OscarTypeConvert.java
  42. 86 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/PostgreSqlTypeConvert.java
  43. 99 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqlServerTypeConvert.java
  44. 57 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqliteTypeConvert.java
  45. 100 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/TypeConverts.java
  46. 16 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/package-info.java
  47. 49 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/Branch.java
  48. 44 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/BranchBuilder.java
  49. 95 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/Selector.java
  50. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/package-info.java
  51. 52 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/LikeTable.java
  52. 448 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableField.java
  53. 357 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java
  54. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/package-info.java
  55. 42 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/AbstractDbQuery.java
  56. 77 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/ClickHouseQuery.java
  57. 73 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DB2Query.java
  58. 79 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DMQuery.java
  59. 290 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DbQueryDecorator.java
  60. 56 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DbQueryRegistry.java
  61. 95 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/FirebirdQuery.java
  62. 77 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/GaussQuery.java
  63. 110 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/GbaseQuery.java
  64. 75 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/H2Query.java
  65. 75 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/KingbaseESQuery.java
  66. 81 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/MariadbQuery.java
  67. 81 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/MySqlQuery.java
  68. 82 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/OracleQuery.java
  69. 66 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/OscarQuery.java
  70. 97 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/PostgreSqlQuery.java
  71. 97 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SqlServerQuery.java
  72. 72 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SqliteQuery.java
  73. 67 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SybaseQuery.java
  74. 67 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/XuguQuery.java
  75. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/package-info.java
  76. 38 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DateType.java
  77. 93 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbColumnType.java
  78. 39 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/IColumnType.java
  79. 142 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/NamingStrategy.java
  80. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/package-info.java
  81. 373 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/AbstractTemplateEngine.java
  82. 82 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/BeetlTemplateEngine.java
  83. 49 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/EnjoyTemplateEngine.java
  84. 62 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/FreemarkerTemplateEngine.java
  85. 84 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/VelocityTemplateEngine.java
  86. 53 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/fill/Column.java
  87. 53 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/fill/Property.java
  88. 32 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/function/ConverterFileName.java
  89. 238 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/jdbc/DatabaseMetaDataWrapper.java
  90. 55 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/BaseKeyWordsHandler.java
  91. 135 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/H2KeyWordsHandler.java
  92. 808 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/MySqlKeyWordsHandler.java
  93. 155 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/PostgreSqlKeyWordsHandler.java
  94. 23 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/package-info.java
  95. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/package-info.java
  96. 104 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/AbstractDatabaseQuery.java
  97. 132 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/DefaultQuery.java
  98. 37 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/IDatabaseQuery.java
  99. 137 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/SQLQuery.java
  100. 42 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/type/ITypeConvertHandler.java

+ 8 - 1
build.gradle

@@ -68,7 +68,14 @@ ext {
         //cache
         "mybatis-ehcache"            : "org.mybatis.caches:mybatis-ehcache:1.2.1",
         "mybatis-redis"              : "org.mybatis.caches:mybatis-redis:1.0.0-beta2",
-        "mybatis-caffeine"           : "org.mybatis.caches:mybatis-caffeine:1.0.0"
+        "mybatis-caffeine"           : "org.mybatis.caches:mybatis-caffeine:1.0.0",
+        //code generator
+//        "mybatis-plus"        : "com.baomidou:mybatis-plus:${mybatisPlusVersion}",
+        "velocity"            : "org.apache.velocity:velocity-engine-core:2.3",
+        "freemarker"          : "org.freemarker:freemarker:2.3.31",
+        "beetl"               : "com.ibeetl:beetl:3.7.0.RELEASE",
+        "swagger-annotations" : "io.swagger:swagger-annotations:1.6.2",
+        "enjoy"               : "com.jfinal:enjoy:5.0.0",
     ]
 }
 

二進制
libs/DmJdbcDriver-1.7.0.jar


二進制
libs/ojdbc8.jar


+ 1 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/LambdaQueryChainWrapper.java

@@ -34,7 +34,7 @@ public class LambdaQueryChainWrapper<T> extends AbstractChainWrapper<T, SFunctio
     implements ChainQuery<T>, Query<LambdaQueryChainWrapper<T>, T, SFunction<T, ?>> {
 
     private final BaseMapper<T> baseMapper;
-    private final Class<T> entityClass;
+    private Class<T> entityClass;
 
     public LambdaQueryChainWrapper(BaseMapper<T> baseMapper) {
         super();

+ 19 - 0
mybatis-plus-generator/build.gradle

@@ -0,0 +1,19 @@
+dependencies {
+    implementation project(":mybatis-plus-extension")
+    implementation "${lib.velocity}"
+    implementation "${lib.freemarker}"
+    implementation "${lib.beetl}"
+    implementation "${lib.enjoy}"
+
+    compileOnly "org.jetbrains:annotations:22.0.0"
+    testImplementation "${lib.sqlserver}"
+    testImplementation "${lib.postgresql}"
+    testImplementation lib.oracle as ConfigurableFileTree
+    testImplementation lib.dm as ConfigurableFileTree
+    testImplementation "${lib.h2}"
+    testImplementation "${lib.mysql}"
+    testImplementation "${lib.sqlite}"
+    testImplementation "${lib.firebird}"
+    testImplementation "${lib.'swagger-annotations'}"
+    testCompileOnly "org.jetbrains:annotations:22.0.0"
+}

+ 221 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/AutoGenerator.java

@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator;
+
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
+import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * 生成文件
+ *
+ * @author YangHu, tangguo, hubin
+ * @since 2016-08-30
+ */
+public class AutoGenerator {
+
+    private static final Logger logger = LoggerFactory.getLogger(AutoGenerator.class);
+
+    /**
+     * 配置信息
+     */
+    protected ConfigBuilder config;
+    /**
+     * 注入配置
+     */
+    protected InjectionConfig injection;
+    /**
+     * 数据源配置
+     */
+    private DataSourceConfig dataSource;
+    /**
+     * 数据库表配置
+     */
+    private StrategyConfig strategy;
+    /**
+     * 包 相关配置
+     */
+    private PackageConfig packageInfo;
+    /**
+     * 模板 相关配置
+     */
+    private TemplateConfig template;
+    /**
+     * 全局 相关配置
+     */
+    private GlobalConfig globalConfig;
+
+    private AutoGenerator() {
+        // 不推荐使用
+    }
+
+    /**
+     * 构造方法
+     *
+     * @param dataSourceConfig 数据库配置
+     * @since 3.5.0
+     */
+    public AutoGenerator(@NotNull DataSourceConfig dataSourceConfig) {
+        //这个是必须参数,其他都是可选的,后续去除默认构造更改成final
+        this.dataSource = dataSourceConfig;
+    }
+
+    /**
+     * 注入配置
+     *
+     * @param injectionConfig 注入配置
+     * @return this
+     * @since 3.5.0
+     */
+    public AutoGenerator injection(@NotNull InjectionConfig injectionConfig) {
+        this.injection = injectionConfig;
+        return this;
+    }
+
+    /**
+     * 生成策略
+     *
+     * @param strategyConfig 策略配置
+     * @return this
+     * @since 3.5.0
+     */
+    public AutoGenerator strategy(@NotNull StrategyConfig strategyConfig) {
+        this.strategy = strategyConfig;
+        return this;
+    }
+
+    /**
+     * 指定包配置信息
+     *
+     * @param packageConfig 包配置
+     * @return this
+     * @since 3.5.0
+     */
+    public AutoGenerator packageInfo(@NotNull PackageConfig packageConfig) {
+        this.packageInfo = packageConfig;
+        return this;
+    }
+
+    /**
+     * 指定模板配置
+     *
+     * @param templateConfig 模板配置
+     * @return this
+     * @since 3.5.0
+     */
+    public AutoGenerator template(@NotNull TemplateConfig templateConfig) {
+        this.template = templateConfig;
+        return this;
+    }
+
+    /**
+     * 指定全局配置
+     *
+     * @param globalConfig 全局配置
+     * @return this
+     * @see 3.5.0
+     */
+    public AutoGenerator global(@NotNull GlobalConfig globalConfig) {
+        this.globalConfig = globalConfig;
+        return this;
+    }
+
+    /**
+     * 设置配置汇总
+     *
+     * @param configBuilder 配置汇总
+     * @return this
+     * @since 3.5.0
+     */
+    public AutoGenerator config(@NotNull ConfigBuilder configBuilder) {
+        this.config = configBuilder;
+        return this;
+    }
+
+    /**
+     * 生成代码
+     */
+    public void execute() {
+        this.execute(null);
+    }
+
+    /**
+     * 生成代码
+     *
+     * @param templateEngine 模板引擎
+     */
+    public void execute(AbstractTemplateEngine templateEngine) {
+        logger.debug("==========================准备生成文件...==========================");
+        // 初始化配置
+        if (null == config) {
+            config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig, injection);
+        }
+        if (null == templateEngine) {
+            // 为了兼容之前逻辑,采用 Velocity 引擎 【 默认 】
+            templateEngine = new VelocityTemplateEngine();
+        }
+        templateEngine.setConfigBuilder(config);
+        // 模板引擎初始化执行文件输出
+        templateEngine.init(config).batchOutput().open();
+        logger.debug("==========================文件生成完成!!!==========================");
+    }
+
+    /**
+     * 开放表信息、预留子类重写
+     *
+     * @param config 配置信息
+     * @return ignore
+     */
+    @NotNull
+    protected List<TableInfo> getAllTableInfoList(@NotNull ConfigBuilder config) {
+        return config.getTableInfoList();
+    }
+
+    public ConfigBuilder getConfig() {
+        return config;
+    }
+
+    public InjectionConfig getInjectionConfig() {
+        return injection;
+    }
+
+    public DataSourceConfig getDataSource() {
+        return dataSource;
+    }
+
+    public StrategyConfig getStrategy() {
+        return strategy;
+    }
+
+    public PackageConfig getPackageInfo() {
+        return packageInfo;
+    }
+
+    public TemplateConfig getTemplate() {
+        return template;
+    }
+
+    public GlobalConfig getGlobalConfig() {
+        return globalConfig;
+    }
+}

+ 231 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/FastAutoGenerator.java

@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Scanner;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * mybatis plus FastAutoGenerator
+ *
+ * @author L.cm, lanjerry
+ * @since 2021-07-22
+ */
+public final class FastAutoGenerator {
+
+    /**
+     * 数据源配置 Builder
+     */
+    private final DataSourceConfig.Builder dataSourceConfigBuilder;
+
+    /**
+     * 全局配置 Builder
+     */
+    private final GlobalConfig.Builder globalConfigBuilder;
+
+    /**
+     * 包配置 Builder
+     */
+    private final PackageConfig.Builder packageConfigBuilder;
+
+    /**
+     * 策略配置 Builder
+     */
+    private final StrategyConfig.Builder strategyConfigBuilder;
+
+    /**
+     * 注入配置 Builder
+     */
+    private final InjectionConfig.Builder injectionConfigBuilder;
+
+    /**
+     * 模板配置 Builder
+     */
+    private final TemplateConfig.Builder templateConfigBuilder;
+
+    /**
+     * 模板引擎
+     */
+    private AbstractTemplateEngine templateEngine;
+
+    private FastAutoGenerator(DataSourceConfig.Builder dataSourceConfigBuilder) {
+        this.dataSourceConfigBuilder = dataSourceConfigBuilder;
+        this.globalConfigBuilder = new GlobalConfig.Builder();
+        this.packageConfigBuilder = new PackageConfig.Builder();
+        this.strategyConfigBuilder = new StrategyConfig.Builder();
+        this.injectionConfigBuilder = new InjectionConfig.Builder();
+        this.templateConfigBuilder = new TemplateConfig.Builder();
+    }
+
+    public static FastAutoGenerator create(@NotNull String url, String username, String password) {
+        return new FastAutoGenerator(new DataSourceConfig.Builder(url, username, password));
+    }
+
+    public static FastAutoGenerator create(@NotNull DataSourceConfig.Builder dataSourceConfigBuilder) {
+        return new FastAutoGenerator(dataSourceConfigBuilder);
+    }
+
+    /**
+     * 读取控制台输入内容
+     */
+    private final Scanner scanner = new Scanner(System.in);
+
+    /**
+     * 控制台输入内容读取并打印提示信息
+     *
+     * @param message 提示信息
+     * @return String
+     */
+    public String scannerNext(String message) {
+        System.out.println(message);
+        String nextLine = scanner.nextLine();
+        if (StringUtils.isBlank(nextLine)) {
+            // 如果输入空行继续等待
+            return scanner.next();
+        }
+        return nextLine;
+    }
+
+    /**
+     * 全局配置
+     *
+     * @param consumer 自定义全局配置
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator dataSourceConfig(Consumer<DataSourceConfig.Builder> consumer) {
+        consumer.accept(this.dataSourceConfigBuilder);
+        return this;
+    }
+
+    public FastAutoGenerator dataSourceConfig(BiConsumer<Function<String, String>, DataSourceConfig.Builder> biConsumer) {
+        biConsumer.accept(this::scannerNext, this.dataSourceConfigBuilder);
+        return this;
+    }
+
+    /**
+     * 全局配置
+     *
+     * @param consumer 自定义全局配置
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator globalConfig(Consumer<GlobalConfig.Builder> consumer) {
+        consumer.accept(this.globalConfigBuilder);
+        return this;
+    }
+
+    public FastAutoGenerator globalConfig(BiConsumer<Function<String, String>, GlobalConfig.Builder> biConsumer) {
+        biConsumer.accept(this::scannerNext, this.globalConfigBuilder);
+        return this;
+    }
+
+    /**
+     * 包配置
+     *
+     * @param consumer 自定义包配置
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator packageConfig(Consumer<PackageConfig.Builder> consumer) {
+        consumer.accept(this.packageConfigBuilder);
+        return this;
+    }
+
+    public FastAutoGenerator packageConfig(BiConsumer<Function<String, String>, PackageConfig.Builder> biConsumer) {
+        biConsumer.accept(this::scannerNext, this.packageConfigBuilder);
+        return this;
+    }
+
+    /**
+     * 策略配置
+     *
+     * @param consumer 自定义策略配置
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator strategyConfig(Consumer<StrategyConfig.Builder> consumer) {
+        consumer.accept(this.strategyConfigBuilder);
+        return this;
+    }
+
+    public FastAutoGenerator strategyConfig(BiConsumer<Function<String, String>, StrategyConfig.Builder> biConsumer) {
+        biConsumer.accept(this::scannerNext, this.strategyConfigBuilder);
+        return this;
+    }
+
+    /**
+     * 注入配置
+     *
+     * @param consumer 自定义注入配置
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator injectionConfig(Consumer<InjectionConfig.Builder> consumer) {
+        consumer.accept(this.injectionConfigBuilder);
+        return this;
+    }
+
+    public FastAutoGenerator injectionConfig(BiConsumer<Function<String, String>, InjectionConfig.Builder> biConsumer) {
+        biConsumer.accept(this::scannerNext, this.injectionConfigBuilder);
+        return this;
+    }
+
+    /**
+     * 模板配置
+     *
+     * @param consumer 自定义模板配置
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator templateConfig(Consumer<TemplateConfig.Builder> consumer) {
+        consumer.accept(this.templateConfigBuilder);
+        return this;
+    }
+
+    public FastAutoGenerator templateConfig(BiConsumer<Function<String, String>, TemplateConfig.Builder> biConsumer) {
+        biConsumer.accept(this::scannerNext, this.templateConfigBuilder);
+        return this;
+    }
+
+    /**
+     * 模板引擎配置
+     *
+     * @param templateEngine 模板引擎
+     * @return FastAutoGenerator
+     */
+    public FastAutoGenerator templateEngine(AbstractTemplateEngine templateEngine) {
+        this.templateEngine = templateEngine;
+        return this;
+    }
+
+    public void execute() {
+        new AutoGenerator(this.dataSourceConfigBuilder.build())
+            // 全局配置
+            .global(this.globalConfigBuilder.build())
+            // 包配置
+            .packageInfo(this.packageConfigBuilder.build())
+            // 策略配置
+            .strategy(this.strategyConfigBuilder.build())
+            // 注入配置
+            .injection(this.injectionConfigBuilder.build())
+            // 模板配置
+            .template(this.templateConfigBuilder.build())
+            // 执行
+            .execute(this.templateEngine);
+    }
+}

+ 35 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/IFill.java

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 填充接口
+ *
+ * @author nieqiurong
+ * @since 3.5.0 2020/11/30.
+ */
+public interface IFill {
+
+    @NotNull
+    String getName();
+
+    @NotNull
+    FieldFill getFieldFill();
+
+}

+ 34 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/ITemplate.java

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator;
+
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+/**
+ * 渲染模板接口
+ *
+ * @author nieqiurong 2020/11/9.
+ * @since 3.5.0
+ */
+public interface ITemplate {
+
+    @NotNull
+    Map<String, Object> renderData(@NotNull TableInfo tableInfo);
+
+}

+ 90 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ConstVal.java

@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 定义常量
+ *
+ * @author YangHu, tangguo, hubin
+ * @since 2016-08-31
+ */
+public interface ConstVal {
+
+    String MODULE_NAME = "ModuleName";
+
+    String ENTITY = "Entity";
+    String SERVICE = "Service";
+    String SERVICE_IMPL = "ServiceImpl";
+    String MAPPER = "Mapper";
+    String XML = "Xml";
+    String CONTROLLER = "Controller";
+    String PARENT = "Parent";
+
+    String JAVA_TMPDIR = "java.io.tmpdir";
+    String UTF8 = StandardCharsets.UTF_8.name();
+    String UNDERLINE = "_";
+
+    String JAVA_SUFFIX = StringPool.DOT_JAVA;
+    String KT_SUFFIX = ".kt";
+    String XML_SUFFIX = ".xml";
+
+    /**
+     * 实体模板路径
+     */
+    String TEMPLATE_ENTITY_JAVA = "/templates/entity.java";
+
+    /**
+     * 实体模板路径(kotlin模板)
+     */
+    String TEMPLATE_ENTITY_KT = "/templates/entity.kt";
+
+    /**
+     * 控制器模板路径
+     */
+    String TEMPLATE_CONTROLLER = "/templates/controller.java";
+
+    /**
+     * Mapper模板路径
+     */
+    String TEMPLATE_MAPPER = "/templates/mapper.java";
+
+    /**
+     * MapperXml模板路径
+     */
+    String TEMPLATE_XML = "/templates/mapper.xml";
+
+    /**
+     * Service模板路径
+     */
+    String TEMPLATE_SERVICE = "/templates/service.java";
+
+    /**
+     * ServiceImpl模板路径
+     */
+    String TEMPLATE_SERVICE_IMPL = "/templates/serviceImpl.java";
+
+    String VM_LOAD_PATH_KEY = "file.resource.loader.class";
+    String VM_LOAD_PATH_VALUE = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
+
+    String SUPER_MAPPER_CLASS = "com.baomidou.mybatisplus.core.mapper.BaseMapper";
+    String SUPER_SERVICE_CLASS = "com.baomidou.mybatisplus.extension.service.IService";
+    String SUPER_SERVICE_IMPL_CLASS = "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl";
+
+}

+ 470 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/DataSourceConfig.java

@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
+import com.baomidou.mybatisplus.generator.config.converts.TypeConverts;
+import com.baomidou.mybatisplus.generator.config.querys.DbQueryDecorator;
+import com.baomidou.mybatisplus.generator.config.querys.DbQueryRegistry;
+import com.baomidou.mybatisplus.generator.query.AbstractDatabaseQuery;
+import com.baomidou.mybatisplus.generator.query.DefaultQuery;
+import com.baomidou.mybatisplus.generator.query.IDatabaseQuery;
+import com.baomidou.mybatisplus.generator.query.SQLQuery;
+import com.baomidou.mybatisplus.generator.type.ITypeConvertHandler;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+/**
+ * 数据库配置
+ *
+ * @author YangHu, hcl, hubin
+ * @since 2016/8/30
+ */
+public class DataSourceConfig {
+    protected final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
+
+    private DataSourceConfig() {
+    }
+
+    /**
+     * 数据库信息查询
+     */
+    private IDbQuery dbQuery;
+
+    /**
+     * schemaName
+     */
+    private String schemaName;
+
+    /**
+     * 类型转换
+     */
+    private ITypeConvert typeConvert;
+
+    /**
+     * 关键字处理器
+     *
+     * @since 3.3.2
+     */
+    private IKeyWordsHandler keyWordsHandler;
+
+    /**
+     * 驱动连接的URL
+     */
+    private String url;
+
+    /**
+     * 数据库连接用户名
+     */
+    private String username;
+
+    /**
+     * 数据库连接密码
+     */
+    private String password;
+
+    /**
+     * 数据源实例
+     *
+     * @since 3.5.0
+     */
+    private DataSource dataSource;
+
+    /**
+     * 数据库连接
+     *
+     * @since 3.5.0
+     */
+    private Connection connection;
+
+    /**
+     * 数据库连接属性
+     *
+     * @since 3.5.3
+     */
+    private final Map<String, String> connectionProperties = new HashMap<>();
+
+    /**
+     * 查询方式
+     *
+     * @see DefaultQuery 默认查询方式,配合{@link #getTypeConvertHandler()} 使用
+     * @see SQLQuery SQL语句查询方式,配合{@link #typeConvert} 使用
+     * @since 3.5.3
+     */
+    private Class<? extends AbstractDatabaseQuery> databaseQueryClass = DefaultQuery.class;
+
+    /**
+     * 类型转换处理
+     *
+     * @since 3.5.3
+     */
+    private ITypeConvertHandler typeConvertHandler;
+
+    /**
+     * 获取数据库查询
+     */
+    @NotNull
+    public IDbQuery getDbQuery() {
+        if (null == dbQuery) {
+            DbType dbType = getDbType();
+            DbQueryRegistry dbQueryRegistry = new DbQueryRegistry();
+            // 默认 MYSQL
+            dbQuery = Optional.ofNullable(dbQueryRegistry.getDbQuery(dbType))
+                .orElseGet(() -> dbQueryRegistry.getDbQuery(DbType.MYSQL));
+        }
+        return dbQuery;
+    }
+
+    /**
+     * 判断数据库类型
+     *
+     * @return 类型枚举值
+     */
+    @NotNull
+    public DbType getDbType() {
+        return this.getDbType(this.url.toLowerCase());
+    }
+
+    /**
+     * 判断数据库类型
+     *
+     * @param str url
+     * @return 类型枚举值,如果没找到,则返回 null
+     */
+    @NotNull
+    private DbType getDbType(@NotNull String str) {
+        if (str.contains(":mysql:") || str.contains(":cobar:")) {
+            return DbType.MYSQL;
+        } else if (str.contains(":oracle:")) {
+            return DbType.ORACLE;
+        } else if (str.contains(":postgresql:")) {
+            return DbType.POSTGRE_SQL;
+        } else if (str.contains(":sqlserver:")) {
+            return DbType.SQL_SERVER;
+        } else if (str.contains(":db2:")) {
+            return DbType.DB2;
+        } else if (str.contains(":mariadb:")) {
+            return DbType.MARIADB;
+        } else if (str.contains(":sqlite:")) {
+            return DbType.SQLITE;
+        } else if (str.contains(":h2:")) {
+            return DbType.H2;
+        } else if (str.contains(":kingbase:") || str.contains(":kingbase8:")) {
+            return DbType.KINGBASE_ES;
+        } else if (str.contains(":dm:")) {
+            return DbType.DM;
+        } else if (str.contains(":zenith:")) {
+            return DbType.GAUSS;
+        } else if (str.contains(":oscar:")) {
+            return DbType.OSCAR;
+        } else if (str.contains(":firebird:")) {
+            return DbType.FIREBIRD;
+        } else if (str.contains(":xugu:")) {
+            return DbType.XU_GU;
+        } else if (str.contains(":clickhouse:")) {
+            return DbType.CLICK_HOUSE;
+        } else if (str.contains(":sybase:")) {
+            return DbType.SYBASE;
+        } else {
+            return DbType.OTHER;
+        }
+    }
+
+    /**
+     * 获取数据库字段类型转换
+     */
+    @NotNull
+    public ITypeConvert getTypeConvert() {
+        if (null == typeConvert) {
+            DbType dbType = getDbType();
+            // 默认 MYSQL
+            typeConvert = TypeConverts.getTypeConvert(dbType);
+            if (null == typeConvert) {
+                typeConvert = MySqlTypeConvert.INSTANCE;
+            }
+        }
+        return typeConvert;
+    }
+
+    /**
+     * 创建数据库连接对象
+     * 这方法建议只调用一次,毕竟只是代码生成,用一个连接就行。
+     *
+     * @return Connection
+     * @see DbQueryDecorator#getConnection()
+     */
+    @NotNull
+    public Connection getConn() {
+        try {
+            if (connection != null && !connection.isClosed()) {
+                return connection;
+            } else {
+                synchronized (this) {
+                    if (dataSource != null) {
+                        connection = dataSource.getConnection();
+                    } else {
+                        Properties properties = new Properties();
+                        connectionProperties.forEach(properties::setProperty);
+                        properties.put("user", username);
+                        properties.put("password", password);
+                        // 使用元数据查询方式时,有些数据库需要增加属性才能读取注释
+                        this.processProperties(properties);
+                        this.connection = DriverManager.getConnection(url, properties);
+                    }
+                }
+            }
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+        return connection;
+    }
+
+    private void processProperties(Properties properties) {
+        if (this.databaseQueryClass.getName().equals(DefaultQuery.class.getName())) {
+            switch (this.getDbType()) {
+                case MYSQL:
+                    properties.put("remarks", "true");
+                    properties.put("useInformationSchema", "true");
+                    break;
+                case ORACLE:
+                    properties.put("remarks", "true");
+                    properties.put("remarksReporting", "true");
+                    break;
+            }
+        }
+    }
+
+    /**
+     * 获取数据库默认schema
+     *
+     * @return 默认schema
+     * @since 3.5.0
+     */
+    @Nullable
+    protected String getDefaultSchema() {
+        DbType dbType = getDbType();
+        String schema = null;
+        if (DbType.POSTGRE_SQL == dbType) {
+            //pg 默认 schema=public
+            schema = "public";
+        } else if (DbType.KINGBASE_ES == dbType) {
+            //kingbase 默认 schema=PUBLIC
+            schema = "PUBLIC";
+        } else if (DbType.DB2 == dbType) {
+            //db2 默认 schema=current schema
+            schema = "current schema";
+        } else if (DbType.ORACLE == dbType) {
+            //oracle 默认 schema=username
+            schema = this.username.toUpperCase();
+        }
+        return schema;
+    }
+
+    @Nullable
+    public String getSchemaName() {
+        return schemaName;
+    }
+
+    @Nullable
+    public IKeyWordsHandler getKeyWordsHandler() {
+        return keyWordsHandler;
+    }
+
+    @NotNull
+    public String getUrl() {
+        return url;
+    }
+
+    @Nullable
+    public String getUsername() {
+        return username;
+    }
+
+    @Nullable
+    public String getPassword() {
+        return password;
+    }
+
+    @NotNull
+    public Class<? extends IDatabaseQuery> getDatabaseQueryClass() {
+        return databaseQueryClass;
+    }
+
+    @Nullable
+    public ITypeConvertHandler getTypeConvertHandler() {
+        return typeConvertHandler;
+    }
+
+    /**
+     * 数据库配置构建者
+     *
+     * @author nieqiurong 2020/10/10.
+     * @since 3.5.0
+     */
+    public static class Builder implements IConfigBuilder<DataSourceConfig> {
+
+        private final DataSourceConfig dataSourceConfig;
+
+        private Builder() {
+            this.dataSourceConfig = new DataSourceConfig();
+        }
+
+        /**
+         * 构造初始化方法
+         *
+         * @param url      数据库连接地址
+         * @param username 数据库账号
+         * @param password 数据库密码
+         */
+        public Builder(@NotNull String url, String username, String password) {
+            this();
+            if (StringUtils.isBlank(url)) {
+                throw new RuntimeException("无法创建文件,请正确输入 url 配置信息!");
+            }
+            this.dataSourceConfig.url = url;
+            this.dataSourceConfig.username = username;
+            this.dataSourceConfig.password = password;
+        }
+
+        /**
+         * 构造初始化方法
+         *
+         * @param dataSource 外部数据源实例
+         */
+        public Builder(@NotNull DataSource dataSource) {
+            this();
+            this.dataSourceConfig.dataSource = dataSource;
+            try {
+                Connection conn = dataSource.getConnection();
+                this.dataSourceConfig.url = conn.getMetaData().getURL();
+                try {
+                    this.dataSourceConfig.schemaName = conn.getSchema();
+                } catch (Throwable exception) {
+                    //ignore  如果使用低版本的驱动,这里由于是1.7新增的方法,所以会报错,如果驱动太低,需要自行指定了。
+                }
+                this.dataSourceConfig.connection = conn;
+                this.dataSourceConfig.username = conn.getMetaData().getUserName();
+            } catch (SQLException ex) {
+                throw new RuntimeException("构建数据库配置对象失败!", ex);
+            }
+        }
+
+        /**
+         * 设置数据库查询实现
+         *
+         * @param dbQuery 数据库查询实现
+         * @return this
+         */
+        public Builder dbQuery(@NotNull IDbQuery dbQuery) {
+            this.dataSourceConfig.dbQuery = dbQuery;
+            return this;
+        }
+
+        /**
+         * 设置数据库schema
+         *
+         * @param schemaName 数据库schema
+         * @return this
+         */
+        public Builder schema(@NotNull String schemaName) {
+            this.dataSourceConfig.schemaName = schemaName;
+            return this;
+        }
+
+        /**
+         * 设置类型转换器
+         *
+         * @param typeConvert 类型转换器
+         * @return this
+         */
+        public Builder typeConvert(@NotNull ITypeConvert typeConvert) {
+            this.dataSourceConfig.typeConvert = typeConvert;
+            return this;
+        }
+
+        /**
+         * 设置数据库关键字处理器
+         *
+         * @param keyWordsHandler 关键字处理器
+         * @return this
+         */
+        public Builder keyWordsHandler(@NotNull IKeyWordsHandler keyWordsHandler) {
+            this.dataSourceConfig.keyWordsHandler = keyWordsHandler;
+            return this;
+        }
+
+        /**
+         * 指定数据库查询方式
+         *
+         * @param databaseQueryClass 查询类
+         * @return this
+         * @since 3.5.3
+         */
+        public Builder databaseQueryClass(@NotNull Class<? extends AbstractDatabaseQuery> databaseQueryClass) {
+            this.dataSourceConfig.databaseQueryClass = databaseQueryClass;
+            return this;
+        }
+
+        /**
+         * 指定类型转换器
+         *
+         * @param typeConvertHandler 类型转换器
+         * @return this
+         * @since 3.5.3
+         */
+        public Builder typeConvertHandler(@NotNull ITypeConvertHandler typeConvertHandler) {
+            this.dataSourceConfig.typeConvertHandler = typeConvertHandler;
+            return this;
+        }
+
+        /**
+         * 增加数据库连接属性
+         *
+         * @param key   属性名
+         * @param value 属性值
+         * @return this
+         * @since 3.5.3
+         */
+        public Builder addConnectionProperty(@NotNull String key, @NotNull String value) {
+            this.dataSourceConfig.connectionProperties.put(key, value);
+            return this;
+        }
+
+
+        /**
+         * 构建数据库配置
+         *
+         * @return 数据库配置
+         */
+        @Override
+        public DataSourceConfig build() {
+            return this.dataSourceConfig;
+        }
+    }
+}

+ 240 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/GlobalConfig.java

@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.generator.config.rules.DateType;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.function.Supplier;
+
+
+/**
+ * 全局配置
+ *
+ * @author hubin
+ * @since 2016-12-02
+ */
+public class GlobalConfig {
+
+    private GlobalConfig() {
+    }
+
+    protected static final Logger LOGGER = LoggerFactory.getLogger(GlobalConfig.class);
+
+    /**
+     * 生成文件的输出目录【 windows:D://  linux or mac:/tmp 】
+     */
+    private String outputDir = System.getProperty("os.name").toLowerCase().contains("windows") ? "D://" : "/tmp";
+
+    /**
+     * 是否覆盖已有文件(默认 false)(已迁移到策略配置中,3.5.4版本会删除此方法)
+     */
+    @Deprecated
+    private boolean fileOverride;
+
+    /**
+     * 是否打开输出目录
+     */
+    private boolean open = true;
+
+    /**
+     * 作者
+     */
+    private String author = "baomidou";
+
+    /**
+     * 开启 Kotlin 模式(默认 false)
+     */
+    private boolean kotlin;
+
+    /**
+     * 开启 swagger 模式(默认 false 与 springdoc 不可同时使用)
+     */
+    private boolean swagger;
+    /**
+     * 开启 springdoc 模式(默认 false 与 swagger 不可同时使用)
+     */
+    private boolean springdoc;
+
+    /**
+     * 时间类型对应策略
+     */
+    private DateType dateType = DateType.TIME_PACK;
+
+    /**
+     * 获取注释日期
+     *
+     * @since 3.5.0
+     */
+    private Supplier<String> commentDate = () -> new SimpleDateFormat("yyyy-MM-dd").format(new Date());
+
+    public String getOutputDir() {
+        return outputDir;
+    }
+
+    /**
+     * 是否覆盖已有文件(已迁移到策略配置中,3.5.4版本会删除此方法)
+     */
+    @Deprecated
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    public boolean isOpen() {
+        return open;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public boolean isKotlin() {
+        return kotlin;
+    }
+
+    public boolean isSwagger() {
+        // springdoc 设置优先于 swagger
+        return springdoc ? false : swagger;
+    }
+
+    public boolean isSpringdoc() {
+        return springdoc;
+    }
+
+    @NotNull
+    public DateType getDateType() {
+        return dateType;
+    }
+
+    @NotNull
+    public String getCommentDate() {
+        return commentDate.get();
+    }
+
+    /**
+     * 全局配置构建
+     *
+     * @author nieqiurong 2020/10/11.
+     * @since 3.5.0
+     */
+    public static class Builder implements IConfigBuilder<GlobalConfig> {
+
+        private final GlobalConfig globalConfig;
+
+        public Builder() {
+            this.globalConfig = new GlobalConfig();
+        }
+
+        /**
+         * 覆盖已有文件(已迁移到策略配置中,3.5.4版本会删除此方法)
+         */
+        @Deprecated
+        public Builder fileOverride() {
+            LOGGER.warn("全局覆盖已有文件的配置已失效,已迁移到策略配置中");
+            this.globalConfig.fileOverride = true;
+            return this;
+        }
+
+        /**
+         * 禁止打开输出目录
+         */
+        public Builder disableOpenDir() {
+            this.globalConfig.open = false;
+            return this;
+        }
+
+        /**
+         * 输出目录
+         */
+        public Builder outputDir(@NotNull String outputDir) {
+            this.globalConfig.outputDir = outputDir;
+            return this;
+        }
+
+        /**
+         * 作者
+         */
+        public Builder author(@NotNull String author) {
+            this.globalConfig.author = author;
+            return this;
+        }
+
+        /**
+         * 开启 kotlin 模式
+         */
+        public Builder enableKotlin() {
+            this.globalConfig.kotlin = true;
+            return this;
+        }
+
+        /**
+         * 开启 swagger 模式
+         */
+        public Builder enableSwagger() {
+            this.globalConfig.swagger = true;
+            return this;
+        }
+
+        /**
+         * 开启 springdoc 模式
+         */
+        public Builder enableSpringdoc() {
+            this.globalConfig.springdoc = true;
+            return this;
+        }
+
+        /**
+         * 时间类型对应策略
+         */
+        public Builder dateType(@NotNull DateType dateType) {
+            this.globalConfig.dateType = dateType;
+            return this;
+        }
+
+        /**
+         * 注释日期获取处理
+         * example: () -> LocalDateTime.now().format(DateTimeFormatter.ISO_DATE)
+         *
+         * @param commentDate 获取注释日期
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder commentDate(@NotNull Supplier<String> commentDate) {
+            this.globalConfig.commentDate = commentDate;
+            return this;
+        }
+
+        /**
+         * 指定注释日期格式化
+         *
+         * @param pattern 格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder commentDate(@NotNull String pattern) {
+            return commentDate(() -> new SimpleDateFormat(pattern).format(new Date()));
+        }
+
+        @Override
+        public GlobalConfig build() {
+            return this.globalConfig;
+        }
+    }
+}

+ 11 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IConfigBuilder.java

@@ -0,0 +1,11 @@
+package com.baomidou.mybatisplus.generator.config;
+
+/**
+ * 配置构建接口
+ *
+ * @param <T>
+ */
+public interface IConfigBuilder<T> {
+
+    T build();
+}

+ 81 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IDbQuery.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * 表数据查询接口
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public interface IDbQuery {
+    /**
+     * 表信息查询 SQL
+     */
+    String tablesSql();
+
+    /**
+     * 表字段信息查询 SQL
+     */
+    String tableFieldsSql();
+
+    /**
+     * 表名称
+     */
+    String tableName();
+
+    /**
+     * 表注释
+     */
+    String tableComment();
+
+    /**
+     * 字段名称
+     */
+    String fieldName();
+
+    /**
+     * 字段类型
+     */
+    String fieldType();
+
+    /**
+     * 字段注释
+     */
+    String fieldComment();
+
+    /**
+     * 主键字段
+     */
+    String fieldKey();
+
+    /**
+     * 判断主键是否为identity
+     *
+     * @param results ResultSet
+     * @return 主键是否为identity
+     * @throws SQLException ignore
+     */
+    boolean isKeyIdentity(ResultSet results) throws SQLException;
+
+    /**
+     * 自定义字段名称
+     */
+    String[] fieldCustom();
+}

+ 67 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IKeyWordsHandler.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 关键字处理接口
+ *
+ * @author nieqiurong 2020/5/7.
+ * @since 3.3.2
+ */
+public interface IKeyWordsHandler {
+
+    /**
+     * 获取关键字
+     *
+     * @return 关键字集合
+     */
+    @NotNull
+    Collection<String> getKeyWords();
+
+    /**
+     * 格式化关键字格式
+     *
+     * @return 格式
+     */
+    @NotNull
+    String formatStyle();
+
+    /**
+     * 是否为关键字
+     *
+     * @param columnName 字段名称
+     * @return 是否为关键字
+     */
+    boolean isKeyWords(@NotNull String columnName);
+
+    /**
+     * 格式化字段
+     *
+     * @param columnName 字段名称
+     * @return 格式化字段
+     */
+    @NotNull
+    default String formatColumn(@NotNull String columnName) {
+        return String.format(formatStyle(), columnName);
+    }
+
+}

+ 96 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/INameConvert.java

@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.po.TableField;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/**
+ * 名称转换接口类
+ *
+ * @author hubin
+ * @since 2017-01-20
+ */
+public interface INameConvert {
+
+    /**
+     * 执行实体名称转换
+     *
+     * @param tableInfo 表信息对象
+     * @return
+     */
+    @NotNull
+    String entityNameConvert(@NotNull TableInfo tableInfo);
+
+    /**
+     * 执行属性名称转换
+     *
+     * @param field 表字段对象,如果属性表字段命名不一致注意 convert 属性的设置
+     * @return
+     */
+    @NotNull
+    String propertyNameConvert(@NotNull TableField field);
+
+    /**
+     * 默认名称转换接口类
+     *
+     * @author nieqiurong 2020/9/20.
+     * @since 3.5.0
+     */
+    class DefaultNameConvert implements INameConvert {
+
+        private final StrategyConfig strategyConfig;
+
+        public DefaultNameConvert(StrategyConfig strategyConfig) {
+            this.strategyConfig = strategyConfig;
+        }
+
+        @Override
+        public @NotNull String entityNameConvert(@NotNull TableInfo tableInfo) {
+            return NamingStrategy.capitalFirst(processName(tableInfo.getName(), strategyConfig.entity().getNaming(), strategyConfig.getTablePrefix(), strategyConfig.getTableSuffix()));
+        }
+
+        @Override
+        public @NotNull String propertyNameConvert(@NotNull TableField field) {
+            return processName(field.getName(), strategyConfig.entity().getColumnNaming(), strategyConfig.getFieldPrefix(), strategyConfig.getFieldSuffix());
+        }
+
+        private String processName(String name, NamingStrategy strategy, Set<String> prefix, Set<String> suffix) {
+            String propertyName = name;
+            // 删除前缀
+            if (prefix.size() > 0) {
+                propertyName = NamingStrategy.removePrefix(propertyName, prefix);
+            }
+            // 删除后缀
+            if (suffix.size() > 0) {
+                propertyName = NamingStrategy.removeSuffix(propertyName, suffix);
+            }
+            if (StringUtils.isBlank(propertyName)) {
+                throw new RuntimeException(String.format("%s 的名称转换结果为空,请检查是否配置问题", name));
+            }
+            // 下划线转驼峰
+            if (NamingStrategy.underline_to_camel.equals(strategy)) {
+                return NamingStrategy.underlineToCamel(propertyName);
+            }
+            return propertyName;
+        }
+    }
+}

+ 51 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ITypeConvert.java

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.generator.config.po.TableField;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 数据库字段类型转换
+ *
+ * @author hubin
+ * @author hanchunlin
+ * @since 2017-01-20
+ */
+public interface ITypeConvert {
+
+    /**
+     * 执行类型转换
+     *
+     * @param globalConfig 全局配置
+     * @param tableField   字段列信息
+     * @return ignore
+     */
+    default IColumnType processTypeConvert(@NotNull GlobalConfig globalConfig, @NotNull TableField tableField) {
+        return processTypeConvert(globalConfig, tableField.getType());
+    }
+
+    /**
+     * 执行类型转换
+     *
+     * @param globalConfig 全局配置
+     * @param fieldType    字段类型
+     * @return ignore
+     */
+    IColumnType processTypeConvert(@NotNull GlobalConfig globalConfig, @NotNull String fieldType);
+
+}

+ 196 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/InjectionConfig.java

@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * 注入配置
+ *
+ * @author hubin
+ * @since 2016-12-07
+ */
+public class InjectionConfig {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(InjectionConfig.class);
+
+    /**
+     * 输出文件之前消费者
+     */
+    private BiConsumer<TableInfo, Map<String, Object>> beforeOutputFileBiConsumer;
+
+    /**
+     * 自定义配置 Map 对象
+     */
+    private Map<String, Object> customMap = new HashMap<>();
+
+    /**
+     * 自定义模板文件,key为文件名称,value为模板路径(已弃用,换成了customFiles,3.5.4版本会删除此方法)
+     */
+    @Deprecated
+    private Map<String, String> customFile = new HashMap<>();
+
+    /**
+     * 自定义模板文件列表
+     *
+     * @since 3.5.3
+     */
+    private List<CustomFile> customFiles = new ArrayList<>();
+
+    /**
+     * 是否覆盖已有文件(默认 false)(已弃用,已放到自定义文件类CustomFile中,3.5.4版本会删除此方法)
+     *
+     * @since 3.5.2
+     */
+    @Deprecated
+    private boolean fileOverride;
+
+    /**
+     * 输出文件前
+     */
+    @NotNull
+    public void beforeOutputFile(TableInfo tableInfo, Map<String, Object> objectMap) {
+        if (!customMap.isEmpty()) {
+            objectMap.putAll(customMap);
+        }
+        if (null != beforeOutputFileBiConsumer) {
+            beforeOutputFileBiConsumer.accept(tableInfo, objectMap);
+        }
+    }
+
+    /**
+     * 获取自定义配置 Map 对象
+     */
+    @NotNull
+    public Map<String, Object> getCustomMap() {
+        return customMap;
+    }
+
+    /**
+     * 已弃用,换成了customFiles,3.5.4版本会删除此方法
+     */
+    @NotNull
+    @Deprecated
+    public Map<String, String> getCustomFile() {
+        return customFile;
+    }
+
+    /**
+     * 获取自定义模板文件列表
+     */
+    @NotNull
+    public List<CustomFile> getCustomFiles() {
+        return customFiles;
+    }
+
+    /**
+     * 已弃用,已放到自定义文件类CustomFile中,3.5.4版本会删除此方法
+     */
+    @Deprecated
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    /**
+     * 构建者
+     */
+    public static class Builder implements IConfigBuilder<InjectionConfig> {
+
+        private final InjectionConfig injectionConfig;
+
+        public Builder() {
+            this.injectionConfig = new InjectionConfig();
+        }
+
+        /**
+         * 输出文件之前消费者
+         *
+         * @param biConsumer 消费者
+         * @return this
+         */
+        public Builder beforeOutputFile(@NotNull BiConsumer<TableInfo, Map<String, Object>> biConsumer) {
+            this.injectionConfig.beforeOutputFileBiConsumer = biConsumer;
+            return this;
+        }
+
+        /**
+         * 自定义配置 Map 对象
+         *
+         * @param customMap Map 对象
+         * @return this
+         */
+        public Builder customMap(@NotNull Map<String, Object> customMap) {
+            this.injectionConfig.customMap = customMap;
+            return this;
+        }
+
+        /**
+         * 自定义配置模板文件
+         *
+         * @param customFile key为文件名称,value为文件路径
+         * @return this
+         */
+        public Builder customFile(@NotNull Map<String, String> customFile) {
+            return customFile(customFile.entrySet().stream()
+                .map(e -> new CustomFile.Builder().fileName(e.getKey()).templatePath(e.getValue()).build())
+                .collect(Collectors.toList()));
+        }
+
+        public Builder customFile(@NotNull CustomFile customFile) {
+            this.injectionConfig.customFiles.add(customFile);
+            return this;
+        }
+
+        public Builder customFile(@NotNull List<CustomFile> customFiles) {
+            this.injectionConfig.customFiles.addAll(customFiles);
+            return this;
+        }
+
+        public Builder customFile(Consumer<CustomFile.Builder> consumer) {
+            CustomFile.Builder builder = new CustomFile.Builder();
+            consumer.accept(builder);
+            this.injectionConfig.customFiles.add(builder.build());
+            return this;
+        }
+
+        /**
+         * 覆盖已有文件(已弃用,已放到自定义文件类CustomFile中,3.5.4版本会删除此方法)
+         */
+        @Deprecated
+        public Builder fileOverride() {
+            LOGGER.warn("fileOverride方法后续会删除,替代方法为enableFileOverride方法");
+            this.injectionConfig.fileOverride = true;
+            return this;
+        }
+
+        @Override
+        public InjectionConfig build() {
+            return this.injectionConfig;
+        }
+    }
+}

+ 37 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/OutputFile.java

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+/**
+ * 输出文件类型
+ *
+ * @author hubin
+ * @since 2021-06-01
+ */
+public enum OutputFile {
+    entity,
+    service,
+    serviceImpl,
+    mapper,
+    xml,
+    controller,
+    /**
+     * 已弃用,已重构自定义文件生成,3.5.4版本会删除
+     */
+    @Deprecated
+    other,
+    parent;
+}

+ 322 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/PackageConfig.java

@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 包相关的配置项
+ *
+ * @author YangHu, tangguo, hubin
+ * @since 2016-08-30
+ */
+public class PackageConfig {
+
+    private PackageConfig() {
+    }
+
+    /**
+     * 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
+     */
+    private String parent = "com.baomidou";
+
+    /**
+     * 父包模块名
+     */
+    private String moduleName = "";
+
+    /**
+     * Entity包名
+     */
+    private String entity = "entity";
+
+    /**
+     * Service包名
+     */
+    private String service = "service";
+
+    /**
+     * Service Impl包名
+     */
+    private String serviceImpl = "service.impl";
+
+    /**
+     * Mapper包名
+     */
+    private String mapper = "mapper";
+
+    /**
+     * Mapper XML包名
+     */
+    private String xml = "mapper.xml";
+
+    /**
+     * Controller包名
+     */
+    private String controller = "controller";
+
+    /**
+     * 路径配置信息
+     */
+    private Map<OutputFile, String> pathInfo;
+
+    /**
+     * 包配置信息
+     *
+     * @since 3.5.0
+     */
+    private final Map<String, String> packageInfo = new HashMap<>();
+
+    /**
+     * 父包名
+     */
+    @NotNull
+    public String getParent() {
+        if (StringUtils.isNotBlank(moduleName)) {
+            return parent + StringPool.DOT + moduleName;
+        }
+        return parent;
+    }
+
+    /**
+     * 连接父子包名
+     *
+     * @param subPackage 子包名
+     * @return 连接后的包名
+     */
+    @NotNull
+    public String joinPackage(String subPackage) {
+        String parent = getParent();
+        return StringUtils.isBlank(parent) ? subPackage : (parent + StringPool.DOT + subPackage);
+    }
+
+    /**
+     * 获取包配置信息
+     *
+     * @return 包配置信息
+     * @since 3.5.0
+     */
+    @NotNull
+    public Map<String, String> getPackageInfo() {
+        if (packageInfo.isEmpty()) {
+            packageInfo.put(ConstVal.MODULE_NAME, this.getModuleName());
+            packageInfo.put(ConstVal.ENTITY, this.joinPackage(this.getEntity()));
+            packageInfo.put(ConstVal.MAPPER, this.joinPackage(this.getMapper()));
+            packageInfo.put(ConstVal.XML, this.joinPackage(this.getXml()));
+            packageInfo.put(ConstVal.SERVICE, this.joinPackage(this.getService()));
+            packageInfo.put(ConstVal.SERVICE_IMPL, this.joinPackage(this.getServiceImpl()));
+            packageInfo.put(ConstVal.CONTROLLER, this.joinPackage(this.getController()));
+            packageInfo.put(ConstVal.PARENT, this.getParent());
+        }
+        return Collections.unmodifiableMap(this.packageInfo);
+    }
+
+    /**
+     * 获取包配置信息
+     *
+     * @param module 模块
+     * @return 配置信息
+     * @since 3.5.0
+     */
+    public String getPackageInfo(String module) {
+        return getPackageInfo().get(module);
+    }
+
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    public String getEntity() {
+        return entity;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    public String getServiceImpl() {
+        return serviceImpl;
+    }
+
+    public String getMapper() {
+        return mapper;
+    }
+
+    public String getXml() {
+        return xml;
+    }
+
+    public String getController() {
+        return controller;
+    }
+
+    public Map<OutputFile, String> getPathInfo() {
+        return pathInfo;
+    }
+
+    /**
+     * 构建者
+     *
+     * @author nieqiurong
+     * @since 3.5.0
+     */
+    public static class Builder implements IConfigBuilder<PackageConfig> {
+
+        private final PackageConfig packageConfig;
+
+        public Builder() {
+            this.packageConfig = new PackageConfig();
+        }
+
+        public Builder(@NotNull String parent, @NotNull String moduleName) {
+            this();
+            this.packageConfig.parent = parent;
+            this.packageConfig.moduleName = moduleName;
+        }
+
+        /**
+         * 指定父包名
+         *
+         * @param parent 父包名
+         * @return this
+         */
+        public Builder parent(@NotNull String parent) {
+            this.packageConfig.parent = parent;
+            return this;
+        }
+
+        /**
+         * 指定模块名称
+         *
+         * @param moduleName 模块名
+         * @return this
+         */
+        public Builder moduleName(@NotNull String moduleName) {
+            this.packageConfig.moduleName = moduleName;
+            return this;
+        }
+
+        /**
+         * 指定实体包名
+         *
+         * @param entity 实体包名
+         * @return this
+         */
+        public Builder entity(@NotNull String entity) {
+            this.packageConfig.entity = entity;
+            return this;
+        }
+
+        /**
+         * 指定service接口包名
+         *
+         * @param service service包名
+         * @return this
+         */
+        public Builder service(@NotNull String service) {
+            this.packageConfig.service = service;
+            return this;
+        }
+
+        /**
+         * service实现类包名
+         *
+         * @param serviceImpl service实现类包名
+         * @return this
+         */
+        public Builder serviceImpl(@NotNull String serviceImpl) {
+            this.packageConfig.serviceImpl = serviceImpl;
+            return this;
+        }
+
+        /**
+         * 指定mapper接口包名
+         *
+         * @param mapper mapper包名
+         * @return this
+         */
+        public Builder mapper(@NotNull String mapper) {
+            this.packageConfig.mapper = mapper;
+            return this;
+        }
+
+        /**
+         * 指定xml包名
+         *
+         * @param xml xml包名
+         * @return this
+         */
+        public Builder xml(@NotNull String xml) {
+            this.packageConfig.xml = xml;
+            return this;
+        }
+
+        /**
+         * 指定控制器包名
+         *
+         * @param controller 控制器包名
+         * @return this
+         */
+        public Builder controller(@NotNull String controller) {
+            this.packageConfig.controller = controller;
+            return this;
+        }
+
+        /**
+         * 路径配置信息
+         *
+         * @param pathInfo 路径配置信息
+         * @return this
+         */
+        public Builder pathInfo(@NotNull Map<OutputFile, String> pathInfo) {
+            this.packageConfig.pathInfo = pathInfo;
+            return this;
+        }
+
+        /**
+         * 连接父子包名
+         *
+         * @param subPackage 子包名
+         * @return 连接后的包名
+         */
+        @NotNull
+        public String joinPackage(@NotNull String subPackage) {
+            return this.packageConfig.joinPackage(subPackage);
+        }
+
+        /**
+         * 构建包配置对象
+         * <p>当指定{@link #parent(String)} 与 {@link #moduleName(String)}时,其他模块名字会加上这两个作为前缀</p>
+         * <p>
+         * 例如:
+         * <p>当设置 {@link #parent(String)},那么entity的配置为 {@link #getParent()}.{@link #getEntity()}</p>
+         * <p>当设置 {@link #parent(String)}与{@link #moduleName(String)},那么entity的配置为 {@link #getParent()}.{@link #getModuleName()}.{@link #getEntity()} </p>
+         * </p>
+         *
+         * @return 包配置对象
+         */
+        @Override
+        public PackageConfig build() {
+            return this.packageConfig;
+        }
+    }
+}

+ 556 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/StrategyConfig.java

@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.builder.*;
+import com.baomidou.mybatisplus.generator.config.po.LikeTable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 策略配置项
+ *
+ * @author YangHu, tangguo, hubin
+ * @since 2016/8/30
+ */
+public class StrategyConfig {
+
+    private StrategyConfig() {
+    }
+
+    /**
+     * 是否大写命名(默认 false)
+     */
+    private boolean isCapitalMode;
+
+    /**
+     * 是否跳过视图(默认 false)
+     */
+    private boolean skipView;
+
+    /**
+     * 过滤表前缀
+     * example: addTablePrefix("t_")
+     * result: t_simple -> Simple
+     */
+    private final Set<String> tablePrefix = new HashSet<>();
+
+    /**
+     * 过滤表后缀
+     * example: addTableSuffix("_0")
+     * result: t_simple_0 -> Simple
+     */
+    private final Set<String> tableSuffix = new HashSet<>();
+
+    /**
+     * 过滤字段前缀
+     * example: addFieldPrefix("is_")
+     * result: is_deleted -> deleted
+     */
+    private final Set<String> fieldPrefix = new HashSet<>();
+
+    /**
+     * 过滤字段后缀
+     * example: addFieldSuffix("_flag")
+     * result: deleted_flag -> deleted
+     */
+    private final Set<String> fieldSuffix = new HashSet<>();
+
+    /**
+     * 需要包含的表名,允许正则表达式(与exclude二选一配置)<br/>
+     * 当{@link #enableSqlFilter}为true时,正则表达式无效.
+     */
+    private final Set<String> include = new HashSet<>();
+
+    /**
+     * 需要排除的表名,允许正则表达式<br/>
+     * 当{@link #enableSqlFilter}为true时,正则表达式无效.
+     */
+    private final Set<String> exclude = new HashSet<>();
+
+    /**
+     * 启用sql过滤,语法不能支持使用sql过滤表的话,可以考虑关闭此开关.
+     *
+     * @since 3.3.1
+     */
+    private boolean enableSqlFilter = true;
+
+    /**
+     * 启用 schema 默认 false
+     */
+    private boolean enableSchema;
+
+    /**
+     * 包含表名
+     *
+     * @since 3.3.0
+     */
+    private LikeTable likeTable;
+
+    /**
+     * 不包含表名
+     *
+     * @since 3.3.0
+     */
+    private LikeTable notLikeTable;
+
+    private final Entity.Builder entityBuilder = new Entity.Builder(this);
+
+    private final Controller.Builder controllerBuilder = new Controller.Builder(this);
+
+    private final Mapper.Builder mapperBuilder = new Mapper.Builder(this);
+
+    private final Service.Builder serviceBuilder = new Service.Builder(this);
+
+    private Entity entity;
+
+    private Controller controller;
+
+    private Mapper mapper;
+
+    private Service service;
+
+    /**
+     * 实体配置构建者
+     *
+     * @return 实体配置构建者
+     * @since 3.5.0
+     */
+    @NotNull
+    public Entity.Builder entityBuilder() {
+        return entityBuilder;
+    }
+
+    /**
+     * 实体配置
+     *
+     * @return 实体配置
+     * @since 3.5.0
+     */
+    @NotNull
+    public Entity entity() {
+        if (entity == null) {
+            this.entity = entityBuilder.get();
+        }
+        return entity;
+    }
+
+    /**
+     * 控制器配置构建者
+     *
+     * @return 控制器配置构建者
+     * @since 3.5.0
+     */
+    @NotNull
+    public Controller.Builder controllerBuilder() {
+        return controllerBuilder;
+    }
+
+    /**
+     * 控制器配置
+     *
+     * @return 控制器配置
+     * @since 3.5.0
+     */
+    @NotNull
+    public Controller controller() {
+        if (controller == null) {
+            this.controller = controllerBuilder.get();
+        }
+        return controller;
+    }
+
+    /**
+     * Mapper配置构建者
+     *
+     * @return Mapper配置构建者
+     * @since 3.5.0
+     */
+    @NotNull
+    public Mapper.Builder mapperBuilder() {
+        return mapperBuilder;
+    }
+
+    /**
+     * Mapper配置
+     *
+     * @return Mapper配置
+     * @since 3.5.0
+     */
+    @NotNull
+    public Mapper mapper() {
+        if (mapper == null) {
+            this.mapper = mapperBuilder.get();
+        }
+        return mapper;
+    }
+
+    /**
+     * Service配置构建者
+     *
+     * @return Service配置构建者
+     * @since 3.5.0
+     */
+    @NotNull
+    public Service.Builder serviceBuilder() {
+        return serviceBuilder;
+    }
+
+    /**
+     * Service配置
+     *
+     * @return Service配置
+     * @since 3.5.0
+     */
+    @NotNull
+    public Service service() {
+        if (service == null) {
+            this.service = serviceBuilder.get();
+        }
+        return service;
+    }
+
+    /**
+     * 大写命名、字段符合大写字母数字下划线命名
+     *
+     * @param word 待判断字符串
+     */
+    public boolean isCapitalModeNaming(@NotNull String word) {
+        return isCapitalMode && StringUtils.isCapitalMode(word);
+    }
+
+    /**
+     * 表名称匹配过滤表前缀
+     *
+     * @param tableName 表名称
+     * @since 3.3.2
+     */
+    public boolean startsWithTablePrefix(@NotNull String tableName) {
+        return this.tablePrefix.stream().anyMatch(tableName::startsWith);
+    }
+
+    /**
+     * 验证配置项
+     *
+     * @since 3.5.0
+     */
+    public void validate() {
+        boolean isInclude = this.getInclude().size() > 0;
+        boolean isExclude = this.getExclude().size() > 0;
+        if (isInclude && isExclude) {
+            throw new IllegalArgumentException("<strategy> 标签中 <include> 与 <exclude> 只能配置一项!");
+        }
+        if (this.getNotLikeTable() != null && this.getLikeTable() != null) {
+            throw new IllegalArgumentException("<strategy> 标签中 <likeTable> 与 <notLikeTable> 只能配置一项!");
+        }
+    }
+
+    /**
+     * 包含表名匹配
+     *
+     * @param tableName 表名
+     * @return 是否匹配
+     * @since 3.5.0
+     */
+    public boolean matchIncludeTable(@NotNull String tableName) {
+        return matchTable(tableName, this.getInclude());
+    }
+
+    /**
+     * 排除表名匹配
+     *
+     * @param tableName 表名
+     * @return 是否匹配
+     * @since 3.5.0
+     */
+    public boolean matchExcludeTable(@NotNull String tableName) {
+        return matchTable(tableName, this.getExclude());
+    }
+
+    /**
+     * 表名匹配
+     *
+     * @param tableName   表名
+     * @param matchTables 匹配集合
+     * @return 是否匹配
+     * @since 3.5.0
+     */
+    private boolean matchTable(@NotNull String tableName, @NotNull Set<String> matchTables) {
+        return matchTables.stream().anyMatch(t -> tableNameMatches(t, tableName));
+    }
+
+    /**
+     * 表名匹配
+     *
+     * @param matchTableName 匹配表名
+     * @param dbTableName    数据库表名
+     * @return 是否匹配
+     */
+    private boolean tableNameMatches(@NotNull String matchTableName, @NotNull String dbTableName) {
+        return matchTableName.equalsIgnoreCase(dbTableName) || StringUtils.matches(matchTableName, dbTableName);
+    }
+
+    public boolean isCapitalMode() {
+        return isCapitalMode;
+    }
+
+    public boolean isSkipView() {
+        return skipView;
+    }
+
+    @NotNull
+    public Set<String> getTablePrefix() {
+        return tablePrefix;
+    }
+
+    @NotNull
+    public Set<String> getTableSuffix() {
+        return tableSuffix;
+    }
+
+    @NotNull
+    public Set<String> getFieldPrefix() {
+        return fieldPrefix;
+    }
+
+    @NotNull
+    public Set<String> getFieldSuffix() {
+        return fieldSuffix;
+    }
+
+    @NotNull
+    public Set<String> getInclude() {
+        return include;
+    }
+
+    @NotNull
+    public Set<String> getExclude() {
+        return exclude;
+    }
+
+    public boolean isEnableSqlFilter() {
+        return enableSqlFilter;
+    }
+
+    public boolean isEnableSchema() {
+        return enableSchema;
+    }
+
+    @Nullable
+    public LikeTable getLikeTable() {
+        return likeTable;
+    }
+
+    @Nullable
+    public LikeTable getNotLikeTable() {
+        return notLikeTable;
+    }
+
+    /**
+     * 策略配置构建者
+     *
+     * @author nieqiurong 2020/10/11.
+     * @since 3.5.0
+     */
+    public static class Builder extends BaseBuilder {
+
+        private final StrategyConfig strategyConfig;
+
+        public Builder() {
+            super(new StrategyConfig());
+            strategyConfig = super.build();
+        }
+
+        /**
+         * 开启大写命名
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableCapitalMode() {
+            this.strategyConfig.isCapitalMode = true;
+            return this;
+        }
+
+        /**
+         * 开启跳过视图
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableSkipView() {
+            this.strategyConfig.skipView = true;
+            return this;
+        }
+
+        /**
+         * 禁用sql过滤
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder disableSqlFilter() {
+            this.strategyConfig.enableSqlFilter = false;
+            return this;
+        }
+
+        /**
+         * 启用 schema
+         *
+         * @return this
+         * @since 3.5.1
+         */
+        public Builder enableSchema() {
+            this.strategyConfig.enableSchema = true;
+            return this;
+        }
+
+        /**
+         * 增加过滤表前缀
+         *
+         * @param tablePrefix 过滤表前缀
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addTablePrefix(@NotNull String... tablePrefix) {
+            return addTablePrefix(Arrays.asList(tablePrefix));
+        }
+
+        public Builder addTablePrefix(@NotNull List<String> tablePrefixList) {
+            this.strategyConfig.tablePrefix.addAll(tablePrefixList);
+            return this;
+        }
+
+        /**
+         * 增加过滤表后缀
+         *
+         * @param tableSuffix 过滤表后缀
+         * @return this
+         * @since 3.5.1
+         */
+        public Builder addTableSuffix(String... tableSuffix) {
+            return addTableSuffix(Arrays.asList(tableSuffix));
+        }
+
+        public Builder addTableSuffix(@NotNull List<String> tableSuffixList) {
+            this.strategyConfig.tableSuffix.addAll(tableSuffixList);
+            return this;
+        }
+
+        /**
+         * 增加过滤字段前缀
+         *
+         * @param fieldPrefix 过滤字段前缀
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addFieldPrefix(@NotNull String... fieldPrefix) {
+            return addFieldPrefix(Arrays.asList(fieldPrefix));
+        }
+
+        public Builder addFieldPrefix(@NotNull List<String> fieldPrefix) {
+            this.strategyConfig.fieldPrefix.addAll(fieldPrefix);
+            return this;
+        }
+
+        /**
+         * 增加过滤字段后缀
+         *
+         * @param fieldSuffix 过滤字段后缀
+         * @return this
+         * @since 3.5.1
+         */
+        public Builder addFieldSuffix(@NotNull String... fieldSuffix) {
+            return addFieldSuffix(Arrays.asList(fieldSuffix));
+        }
+
+        public Builder addFieldSuffix(@NotNull List<String> fieldSuffixList) {
+            this.strategyConfig.fieldSuffix.addAll(fieldSuffixList);
+            return this;
+        }
+
+        /**
+         * 增加包含的表名
+         *
+         * @param include 包含表
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addInclude(@NotNull String... include) {
+            this.strategyConfig.include.addAll(Arrays.asList(include));
+            return this;
+        }
+
+        public Builder addInclude(@NotNull List<String> includes) {
+            this.strategyConfig.include.addAll(includes);
+            return this;
+        }
+
+        public Builder addInclude(@NotNull String include) {
+            this.strategyConfig.include.addAll(Arrays.asList(include.split(",")));
+            return this;
+        }
+
+        /**
+         * 增加排除表
+         *
+         * @param exclude 排除表
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addExclude(@NotNull String... exclude) {
+            return addExclude(Arrays.asList(exclude));
+        }
+
+        public Builder addExclude(@NotNull List<String> excludeList) {
+            this.strategyConfig.exclude.addAll(excludeList);
+            return this;
+        }
+
+        /**
+         * 包含表名
+         *
+         * @return this
+         */
+        public Builder likeTable(@NotNull LikeTable likeTable) {
+            this.strategyConfig.likeTable = likeTable;
+            return this;
+        }
+
+        /**
+         * 不包含表名
+         *
+         * @return this
+         */
+        public Builder notLikeTable(@NotNull LikeTable notLikeTable) {
+            this.strategyConfig.notLikeTable = notLikeTable;
+            return this;
+        }
+
+        @Override
+        @NotNull
+        public StrategyConfig build() {
+            this.strategyConfig.validate();
+            return strategyConfig;
+        }
+    }
+}

+ 308 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateConfig.java

@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 模板路径配置项
+ *
+ * @author tzg hubin
+ * @since 2017-06-17
+ */
+public class TemplateConfig {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(TemplateConfig.class);
+
+    /**
+     * 设置实体模板路径
+     */
+    private String entity;
+
+    /**
+     * 设置实体模板路径(kotlin模板)
+     */
+    private String entityKt;
+
+    /**
+     * 设置控制器模板路径
+     */
+    private String controller;
+
+    /**
+     * 设置Mapper模板路径
+     */
+    private String mapper;
+
+    /**
+     * 设置MapperXml模板路径
+     */
+    private String xml;
+
+    /**
+     * 设置Service模板路径
+     */
+    private String service;
+
+    /**
+     * 设置ServiceImpl模板路径
+     */
+    private String serviceImpl;
+
+    /**
+     * 是否禁用实体模板(默认 false)
+     */
+    private boolean disableEntity;
+
+    /**
+     * 不对外爆露
+     */
+    private TemplateConfig() {
+        this.entity = ConstVal.TEMPLATE_ENTITY_JAVA;
+        this.entityKt = ConstVal.TEMPLATE_ENTITY_KT;
+        this.controller = ConstVal.TEMPLATE_CONTROLLER;
+        this.mapper = ConstVal.TEMPLATE_MAPPER;
+        this.xml = ConstVal.TEMPLATE_XML;
+        this.service = ConstVal.TEMPLATE_SERVICE;
+        this.serviceImpl = ConstVal.TEMPLATE_SERVICE_IMPL;
+    }
+
+    /**
+     * 当模板赋值为空时进行日志提示打印
+     *
+     * @param value        模板值
+     * @param templateType 模板类型
+     */
+    private void logger(String value, TemplateType templateType) {
+        if (StringUtils.isBlank(value)) {
+            LOGGER.warn("推荐使用disable(TemplateType.{})方法进行默认模板禁用.", templateType.name());
+        }
+    }
+
+    /**
+     * 获取实体模板路径
+     *
+     * @param kotlin 是否kotlin
+     * @return 模板路径
+     */
+    public String getEntity(boolean kotlin) {
+        if (!this.disableEntity) {
+            if (kotlin) {
+                return StringUtils.isBlank(this.entityKt) ? ConstVal.TEMPLATE_ENTITY_KT : this.entityKt;
+            }
+            return StringUtils.isBlank(this.entity) ? ConstVal.TEMPLATE_ENTITY_JAVA : this.entity;
+        }
+        return null;
+    }
+
+    /**
+     * 禁用模板
+     *
+     * @param templateTypes 模板类型
+     * @return this
+     * @since 3.3.2
+     */
+    public TemplateConfig disable(@NotNull TemplateType... templateTypes) {
+        if (templateTypes != null && templateTypes.length > 0) {
+            for (TemplateType templateType : templateTypes) {
+                switch (templateType) {
+                    case ENTITY:
+                        this.entity = null;
+                        this.entityKt = null;
+                        //暂时没其他多的需求,使用一个单独的boolean变量进行支持一下.
+                        this.disableEntity = true;
+                        break;
+                    case CONTROLLER:
+                        this.controller = null;
+                        break;
+                    case MAPPER:
+                        this.mapper = null;
+                        break;
+                    case XML:
+                        this.xml = null;
+                        break;
+                    case SERVICE:
+                        this.service = null;
+                        break;
+                    case SERVICE_IMPL:
+                        this.serviceImpl = null;
+                        break;
+                    default:
+                }
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 禁用全部模板
+     *
+     * @return this
+     * @since 3.5.0
+     */
+    public TemplateConfig disable() {
+        return disable(TemplateType.values());
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    public String getServiceImpl() {
+        return serviceImpl;
+    }
+
+    public String getMapper() {
+        return mapper;
+    }
+
+    public String getXml() {
+        return xml;
+    }
+
+    public String getController() {
+        return controller;
+    }
+
+    /**
+     * 模板路径配置构建者
+     *
+     * @author nieqiurong 3.5.0
+     */
+    public static class Builder implements IConfigBuilder<TemplateConfig> {
+
+        private final TemplateConfig templateConfig;
+
+        /**
+         * 默认生成一个空的
+         */
+        public Builder() {
+            this.templateConfig = new TemplateConfig();
+        }
+
+        /**
+         * 禁用所有模板
+         *
+         * @return this
+         */
+        public Builder disable() {
+            this.templateConfig.disable();
+            return this;
+        }
+
+        /**
+         * 禁用模板
+         *
+         * @return this
+         */
+        public Builder disable(@NotNull TemplateType... templateTypes) {
+            this.templateConfig.disable(templateTypes);
+            return this;
+        }
+
+        /**
+         * 设置实体模板路径(JAVA)
+         *
+         * @param entityTemplate 实体模板
+         * @return this
+         */
+        public Builder entity(@NotNull String entityTemplate) {
+            this.templateConfig.disableEntity = false;
+            this.templateConfig.entity = entityTemplate;
+            return this;
+        }
+
+        /**
+         * 设置实体模板路径(kotlin)
+         *
+         * @param entityKtTemplate 实体模板
+         * @return this
+         */
+        public Builder entityKt(@NotNull String entityKtTemplate) {
+            this.templateConfig.disableEntity = false;
+            this.templateConfig.entityKt = entityKtTemplate;
+            return this;
+        }
+
+        /**
+         * 设置service模板路径
+         *
+         * @param serviceTemplate     service接口模板路径
+         * @return this
+         */
+        public Builder service(@NotNull String serviceTemplate) {
+            this.templateConfig.service = serviceTemplate;
+            return this;
+        }
+
+        /**
+         * 设置serviceImpl模板路径
+         *
+         * @param serviceImplTemplate service实现类模板路径
+         * @return this
+         */
+        public Builder serviceImpl(@NotNull String serviceImplTemplate) {
+            this.templateConfig.serviceImpl = serviceImplTemplate;
+            return this;
+        }
+
+        /**
+         * 设置mapper模板路径
+         *
+         * @param mapperTemplate mapper模板路径
+         * @return this
+         */
+        public Builder mapper(@NotNull String mapperTemplate) {
+            this.templateConfig.mapper = mapperTemplate;
+            return this;
+        }
+
+        /**
+         * 设置mapperXml模板路径
+         *
+         * @param xmlTemplate xml模板路径
+         * @return this
+         */
+        public Builder xml(@NotNull String xmlTemplate) {
+            this.templateConfig.xml = xmlTemplate;
+            return this;
+        }
+
+        /**
+         * 设置控制器模板路径
+         *
+         * @param controllerTemplate 控制器模板路径
+         * @return this
+         */
+        public Builder controller(@NotNull String controllerTemplate) {
+            this.templateConfig.controller = controllerTemplate;
+            return this;
+        }
+
+        /**
+         * 构建模板配置对象
+         *
+         * @return 模板配置对象
+         */
+        @Override
+        public TemplateConfig build() {
+            return this.templateConfig;
+        }
+    }
+}

+ 28 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateType.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config;
+
+/**
+ * 模板类型
+ *
+ * @author nieqiurong 2020/4/28.
+ * @since 3.3.2
+ */
+public enum TemplateType {
+
+    ENTITY, SERVICE, SERVICE_IMPL, CONTROLLER, MAPPER, XML
+
+}

+ 62 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/BaseBuilder.java

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.generator.config.IConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 配置构建
+ *
+ * @author nieqiurong 2020/10/11.
+ * @since 3.5.0
+ */
+public class BaseBuilder implements IConfigBuilder<StrategyConfig> {
+
+    private final StrategyConfig strategyConfig;
+
+    public BaseBuilder(@NotNull StrategyConfig strategyConfig) {
+        this.strategyConfig = strategyConfig;
+    }
+
+    @NotNull
+    public Entity.Builder entityBuilder() {
+        return strategyConfig.entityBuilder();
+    }
+
+    @NotNull
+    public Controller.Builder controllerBuilder() {
+        return strategyConfig.controllerBuilder();
+    }
+
+    @NotNull
+    public Mapper.Builder mapperBuilder() {
+        return strategyConfig.mapperBuilder();
+    }
+
+    @NotNull
+    public Service.Builder serviceBuilder() {
+        return strategyConfig.serviceBuilder();
+    }
+
+    @NotNull
+    @Override
+    public StrategyConfig build() {
+        this.strategyConfig.validate();
+        return this.strategyConfig;
+    }
+}

+ 189 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/ConfigBuilder.java

@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.query.IDatabaseQuery;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Constructor;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * 配置汇总 传递给文件生成工具
+ *
+ * @author YangHu, tangguo, hubin, Juzi, lanjerry
+ * @since 2016-08-30
+ */
+public class ConfigBuilder {
+
+    /**
+     * 模板路径配置信息
+     */
+    private final TemplateConfig templateConfig;
+
+    /**
+     * 数据库表信息
+     */
+    private final List<TableInfo> tableInfoList = new ArrayList<>();
+
+    /**
+     * 路径配置信息
+     */
+    private final Map<OutputFile, String> pathInfo = new HashMap<>();
+
+    /**
+     * 策略配置信息
+     */
+    private StrategyConfig strategyConfig;
+
+    /**
+     * 全局配置信息
+     */
+    private GlobalConfig globalConfig;
+
+    /**
+     * 注入配置信息
+     */
+    private InjectionConfig injectionConfig;
+
+    /**
+     * 过滤正则
+     */
+    private static final Pattern REGX = Pattern.compile("[~!/@#$%^&*()+\\\\\\[\\]|{};:'\",<.>?]+");
+
+    /**
+     * 包配置信息
+     */
+    private final PackageConfig packageConfig;
+
+    /**
+     * 数据库配置信息
+     */
+    private final DataSourceConfig dataSourceConfig;
+
+    /**
+     * 数据查询实例
+     * @since 3.5.3
+     */
+    private final IDatabaseQuery databaseQuery;
+
+    /**
+     * 在构造器中处理配置
+     *
+     * @param packageConfig    包配置
+     * @param dataSourceConfig 数据源配置
+     * @param strategyConfig   表配置
+     * @param templateConfig   模板配置
+     * @param globalConfig     全局配置
+     */
+    public ConfigBuilder(@Nullable PackageConfig packageConfig, @NotNull DataSourceConfig dataSourceConfig,
+                         @Nullable StrategyConfig strategyConfig, @Nullable TemplateConfig templateConfig,
+                         @Nullable GlobalConfig globalConfig, @Nullable InjectionConfig injectionConfig) {
+        this.dataSourceConfig = dataSourceConfig;
+        this.strategyConfig = Optional.ofNullable(strategyConfig).orElseGet(GeneratorBuilder::strategyConfig);
+        this.globalConfig = Optional.ofNullable(globalConfig).orElseGet(GeneratorBuilder::globalConfig);
+        this.templateConfig = Optional.ofNullable(templateConfig).orElseGet(GeneratorBuilder::templateConfig);
+        this.packageConfig = Optional.ofNullable(packageConfig).orElseGet(GeneratorBuilder::packageConfig);
+        this.injectionConfig = Optional.ofNullable(injectionConfig).orElseGet(GeneratorBuilder::injectionConfig);
+        this.pathInfo.putAll(new PathInfoHandler(this.globalConfig, this.templateConfig, this.packageConfig).getPathInfo());
+        Class<? extends IDatabaseQuery> databaseQueryClass = dataSourceConfig.getDatabaseQueryClass();
+        try {
+            Constructor<? extends IDatabaseQuery> declaredConstructor = databaseQueryClass.getDeclaredConstructor(this.getClass());
+            this.databaseQuery = declaredConstructor.newInstance(this);
+        } catch (ReflectiveOperationException exception) {
+            throw new RuntimeException("创建IDatabaseQuery实例出现错误:", exception);
+        }
+    }
+
+    /**
+     * 判断表名是否为正则表名(这表名规范比较随意,只能尽量匹配上特殊符号)
+     *
+     * @param tableName 表名
+     * @return 是否正则
+     * @since 3.5.0
+     */
+    public static boolean matcherRegTable(@NotNull String tableName) {
+        return REGX.matcher(tableName).find();
+    }
+
+    @NotNull
+    public ConfigBuilder setStrategyConfig(@NotNull StrategyConfig strategyConfig) {
+        this.strategyConfig = strategyConfig;
+        return this;
+    }
+
+    @NotNull
+    public ConfigBuilder setGlobalConfig(@NotNull GlobalConfig globalConfig) {
+        this.globalConfig = globalConfig;
+        return this;
+    }
+
+    @NotNull
+    public ConfigBuilder setInjectionConfig(@NotNull InjectionConfig injectionConfig) {
+        this.injectionConfig = injectionConfig;
+        return this;
+    }
+
+    @NotNull
+    public TemplateConfig getTemplateConfig() {
+        return templateConfig;
+    }
+
+    @NotNull
+    public List<TableInfo> getTableInfoList() {
+        if (tableInfoList.isEmpty()) {
+            List<TableInfo> tableInfos = this.databaseQuery.queryTables();
+            if (!tableInfos.isEmpty()) {
+                this.tableInfoList.addAll(tableInfos);
+            }
+        }
+        return tableInfoList;
+    }
+
+    @NotNull
+    public Map<OutputFile, String> getPathInfo() {
+        return pathInfo;
+    }
+
+    @NotNull
+    public StrategyConfig getStrategyConfig() {
+        return strategyConfig;
+    }
+
+    @NotNull
+    public GlobalConfig getGlobalConfig() {
+        return globalConfig;
+    }
+
+    @Nullable
+    public InjectionConfig getInjectionConfig() {
+        return injectionConfig;
+    }
+
+    @NotNull
+    public PackageConfig getPackageConfig() {
+        return packageConfig;
+    }
+
+    @NotNull
+    public DataSourceConfig getDataSourceConfig() {
+        return dataSourceConfig;
+    }
+}

+ 216 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Controller.java

@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.ITemplate;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.function.ConverterFileName;
+import com.baomidou.mybatisplus.generator.util.ClassUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 控制器属性配置
+ *
+ * @author nieqiurong 2020/10/11.
+ * @since 3.5.0
+ */
+public class Controller implements ITemplate {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(Controller.class);
+
+    private Controller() {
+    }
+
+    /**
+     * 生成 <code>@RestController</code> 控制器(默认 false)
+     * <pre>
+     *      <code>@Controller</code> -> <code>@RestController</code>
+     * </pre>
+     */
+    private boolean restStyle;
+
+    /**
+     * 驼峰转连字符(默认 false)
+     * <pre>
+     *      <code>@RequestMapping("/managerUserActionHistory")</code> -> <code>@RequestMapping("/manager-user-action-history")</code>
+     * </pre>
+     */
+    private boolean hyphenStyle;
+
+    /**
+     * 自定义继承的Controller类全称,带包名
+     */
+    private String superClass;
+
+    /**
+     * 转换输出控制器文件名称
+     *
+     * @since 3.5.0
+     */
+    private ConverterFileName converterFileName = (entityName -> entityName + ConstVal.CONTROLLER);
+
+    /**
+     * 是否覆盖已有文件(默认 false)
+     *
+     * @since 3.5.2
+     */
+    private boolean fileOverride;
+
+    public boolean isRestStyle() {
+        return restStyle;
+    }
+
+    public boolean isHyphenStyle() {
+        return hyphenStyle;
+    }
+
+    @Nullable
+    public String getSuperClass() {
+        return superClass;
+    }
+
+    @NotNull
+    public ConverterFileName getConverterFileName() {
+        return converterFileName;
+    }
+
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    @Override
+    @NotNull
+    public Map<String, Object> renderData(@NotNull TableInfo tableInfo) {
+        Map<String, Object> data = new HashMap<>(5);
+        data.put("controllerMappingHyphen", StringUtils.camelToHyphen(tableInfo.getEntityPath()));
+        data.put("controllerMappingHyphenStyle", this.hyphenStyle);
+        data.put("restControllerStyle", this.restStyle);
+        data.put("superControllerClassPackage", StringUtils.isBlank(superClass) ? null : superClass);
+        data.put("superControllerClass", ClassUtils.getSimpleName(this.superClass));
+        return data;
+    }
+
+    public static class Builder extends BaseBuilder {
+
+        private final Controller controller = new Controller();
+
+        public Builder(@NotNull StrategyConfig strategyConfig) {
+            super(strategyConfig);
+        }
+
+        /**
+         * 父类控制器
+         *
+         * @param clazz 父类控制器
+         * @return this
+         */
+        public Builder superClass(@NotNull Class<?> clazz) {
+            return superClass(clazz.getName());
+        }
+
+        /**
+         * 父类控制器
+         *
+         * @param superClass 父类控制器类名
+         * @return this
+         */
+        public Builder superClass(@NotNull String superClass) {
+            this.controller.superClass = superClass;
+            return this;
+        }
+
+        /**
+         * 开启驼峰转连字符
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableHyphenStyle() {
+            this.controller.hyphenStyle = true;
+            return this;
+        }
+
+        /**
+         * 开启生成@RestController控制器
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableRestStyle() {
+            this.controller.restStyle = true;
+            return this;
+        }
+
+        /**
+         * 转换输出文件名称
+         *
+         * @param converter  转换处理
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder convertFileName(@NotNull ConverterFileName converter) {
+            this.controller.converterFileName = converter;
+            return this;
+        }
+
+        /**
+         * 格式化文件名称
+         *
+         * @param format  格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder formatFileName(@NotNull String format) {
+            return convertFileName((entityName) -> String.format(format, entityName));
+        }
+
+        /**
+         * 覆盖已有文件(该方法后续会删除,替代方法为enableFileOverride方法)
+         *
+         * @see #enableFileOverride()
+         */
+        @Deprecated
+        public Builder fileOverride() {
+            LOGGER.warn("fileOverride方法后续会删除,替代方法为enableFileOverride方法");
+            this.controller.fileOverride = true;
+            return this;
+        }
+
+        /**
+         * 覆盖已有文件
+         *
+         * @since 3.5.3
+         */
+        public Builder enableFileOverride() {
+            this.controller.fileOverride = true;
+            return this;
+        }
+
+        @NotNull
+        public Controller get() {
+            return this.controller;
+        }
+    }
+}

+ 114 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/CustomFile.java

@@ -0,0 +1,114 @@
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.generator.config.IConfigBuilder;
+
+/**
+ * 自定义模板文件配置
+ *
+ * @author xusimin
+ * @since 3.5.3
+ */
+public class CustomFile {
+
+    /**
+     * 文件名称
+     */
+    private String fileName;
+
+    /**
+     * 模板路径
+     */
+    private String templatePath;
+
+    /**
+     * 自定义文件包名
+     */
+    private String packageName;
+
+    /**
+     * 文件路径
+     */
+    private String filePath;
+
+    /**
+     * 是否覆盖已有文件(默认 false)
+     */
+    private boolean fileOverride;
+
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public String getTemplatePath() {
+        return templatePath;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    /**
+     * 构建者
+     */
+    public static class Builder implements IConfigBuilder<CustomFile> {
+
+        private final CustomFile customFile;
+
+        public Builder() {
+            this.customFile = new CustomFile();
+        }
+
+        /**
+         * 文件名
+         */
+        public CustomFile.Builder fileName(String fileName) {
+            this.customFile.fileName = fileName;
+            return this;
+        }
+
+        /**
+         * 模板路径
+         */
+        public CustomFile.Builder templatePath(String templatePath) {
+            this.customFile.templatePath = templatePath;
+            return this;
+        }
+
+        /**
+         * 包路径
+         */
+        public CustomFile.Builder packageName(String packageName) {
+            this.customFile.packageName = packageName;
+            return this;
+        }
+
+        /**
+         * 文件路径,默认为 PackageConfig.parent 路径
+         */
+        public CustomFile.Builder filePath(String filePath) {
+            this.customFile.filePath = filePath;
+            return this;
+        }
+
+        /**
+         * 覆盖已有文件
+         */
+        public CustomFile.Builder enableFileOverride() {
+            this.customFile.fileOverride = true;
+            return this;
+        }
+
+        @Override
+        public CustomFile build() {
+            return this.customFile;
+        }
+    }
+}

+ 657 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Entity.java

@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.IFill;
+import com.baomidou.mybatisplus.generator.ITemplate;
+import com.baomidou.mybatisplus.generator.config.INameConvert;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.function.ConverterFileName;
+import com.baomidou.mybatisplus.generator.util.ClassUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 实体属性配置
+ *
+ * @author nieqiurong 2020/10/11.
+ * @since 3.5.0
+ */
+public class Entity implements ITemplate {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(Entity.class);
+
+    private Entity() {
+    }
+
+    /**
+     * 名称转换
+     */
+    private INameConvert nameConvert;
+
+    /**
+     * 自定义继承的Entity类全称,带包名
+     */
+    private String superClass;
+
+    /**
+     * 自定义基础的Entity类,公共字段
+     */
+    private final Set<String> superEntityColumns = new HashSet<>();
+
+    /**
+     * 自定义忽略字段
+     * https://github.com/baomidou/generator/issues/46
+     */
+    private final Set<String> ignoreColumns = new HashSet<>();
+
+    /**
+     * 实体是否生成 serialVersionUID
+     */
+    private boolean serialVersionUID = true;
+
+    /**
+     * 【实体】是否生成字段常量(默认 false)<br>
+     * -----------------------------------<br>
+     * public static final String ID = "test_id";
+     */
+    private boolean columnConstant;
+
+    /**
+     * 【实体】是否为链式模型(默认 false)
+     *
+     * @since 3.3.2
+     */
+    private boolean chain;
+
+    /**
+     * 【实体】是否为lombok模型(默认 false)<br>
+     * <a href="https://projectlombok.org/">document</a>
+     */
+    private boolean lombok;
+
+    /**
+     * Boolean类型字段是否移除is前缀(默认 false)<br>
+     * 比如 : 数据库字段名称 : 'is_xxx',类型为 : tinyint. 在映射实体的时候则会去掉is,在实体类中映射最终结果为 xxx
+     */
+    private boolean booleanColumnRemoveIsPrefix;
+
+    /**
+     * 是否生成实体时,生成字段注解(默认 false)
+     */
+    private boolean tableFieldAnnotationEnable;
+
+    /**
+     * 乐观锁字段名称(数据库字段)
+     *
+     * @since 3.5.0
+     */
+    private String versionColumnName;
+
+    /**
+     * 乐观锁属性名称(实体字段)
+     *
+     * @since 3.5.0
+     */
+    private String versionPropertyName;
+
+    /**
+     * 逻辑删除字段名称(数据库字段)
+     *
+     * @since 3.5.0
+     */
+    private String logicDeleteColumnName;
+
+    /**
+     * 逻辑删除属性名称(实体字段)
+     *
+     * @since 3.5.0
+     */
+    private String logicDeletePropertyName;
+
+    /**
+     * 表填充字段
+     */
+    private final List<IFill> tableFillList = new ArrayList<>();
+
+    /**
+     * 数据库表映射到实体的命名策略,默认下划线转驼峰命名
+     */
+    private NamingStrategy naming = NamingStrategy.underline_to_camel;
+
+    /**
+     * 数据库表字段映射到实体的命名策略
+     * <p>未指定按照 naming 执行</p>
+     */
+    private NamingStrategy columnNaming = null;
+
+    /**
+     * 开启 ActiveRecord 模式(默认 false)
+     *
+     * @since 3.5.0
+     */
+    private boolean activeRecord;
+
+    /**
+     * 指定生成的主键的ID类型
+     *
+     * @since 3.5.0
+     */
+    private IdType idType;
+
+    /**
+     * 转换输出文件名称
+     *
+     * @since 3.5.0
+     */
+    private ConverterFileName converterFileName = (entityName -> entityName);
+
+    /**
+     * 是否覆盖已有文件(默认 false)
+     *
+     * @since 3.5.2
+     */
+    private boolean fileOverride;
+
+    /**
+     * <p>
+     * 父类 Class 反射属性转换为公共字段
+     * </p>
+     *
+     * @param clazz 实体父类 Class
+     */
+    public void convertSuperEntityColumns(Class<?> clazz) {
+        List<Field> fields = TableInfoHelper.getAllFields(clazz);
+        this.superEntityColumns.addAll(fields.stream().map(field -> {
+            TableId tableId = field.getAnnotation(TableId.class);
+            if (tableId != null && StringUtils.isNotBlank(tableId.value())) {
+                return tableId.value();
+            }
+            TableField tableField = field.getAnnotation(TableField.class);
+            if (tableField != null && StringUtils.isNotBlank(tableField.value())) {
+                return tableField.value();
+            }
+            if (null == columnNaming || columnNaming == NamingStrategy.no_change) {
+                return field.getName();
+            }
+            return StringUtils.camelToUnderline(field.getName());
+        }).collect(Collectors.toSet()));
+    }
+
+    @NotNull
+    public NamingStrategy getColumnNaming() {
+        // 未指定以 naming 策略为准
+        return Optional.ofNullable(columnNaming).orElse(naming);
+    }
+
+    /**
+     * 匹配父类字段(忽略大小写)
+     *
+     * @param fieldName 字段名
+     * @return 是否匹配
+     * @since 3.5.0
+     */
+    public boolean matchSuperEntityColumns(String fieldName) {
+        // 公共字段判断忽略大小写【 部分数据库大小写不敏感 】
+        return superEntityColumns.stream().anyMatch(e -> e.equalsIgnoreCase(fieldName));
+    }
+
+    /**
+     * 匹配忽略字段(忽略大小写)
+     *
+     * @param fieldName 字段名
+     * @return 是否匹配
+     * @since 3.5.0
+     */
+    public boolean matchIgnoreColumns(String fieldName) {
+        return ignoreColumns.stream().anyMatch(e -> e.equalsIgnoreCase(fieldName));
+    }
+
+    @NotNull
+    public INameConvert getNameConvert() {
+        return nameConvert;
+    }
+
+    @Nullable
+    public String getSuperClass() {
+        return superClass;
+    }
+
+    public Set<String> getSuperEntityColumns() {
+        return this.superEntityColumns;
+    }
+
+    public boolean isSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public boolean isColumnConstant() {
+        return columnConstant;
+    }
+
+    public boolean isChain() {
+        return chain;
+    }
+
+    public boolean isLombok() {
+        return lombok;
+    }
+
+    public boolean isBooleanColumnRemoveIsPrefix() {
+        return booleanColumnRemoveIsPrefix;
+    }
+
+    public boolean isTableFieldAnnotationEnable() {
+        return tableFieldAnnotationEnable;
+    }
+
+    @Nullable
+    public String getVersionColumnName() {
+        return versionColumnName;
+    }
+
+    @Nullable
+    public String getVersionPropertyName() {
+        return versionPropertyName;
+    }
+
+    @Nullable
+    public String getLogicDeleteColumnName() {
+        return logicDeleteColumnName;
+    }
+
+    @Nullable
+    public String getLogicDeletePropertyName() {
+        return logicDeletePropertyName;
+    }
+
+    @NotNull
+    public List<IFill> getTableFillList() {
+        return tableFillList;
+    }
+
+    @NotNull
+    public NamingStrategy getNaming() {
+        return naming;
+    }
+
+    public boolean isActiveRecord() {
+        return activeRecord;
+    }
+
+    @Nullable
+    public IdType getIdType() {
+        return idType;
+    }
+
+    @NotNull
+    public ConverterFileName getConverterFileName() {
+        return converterFileName;
+    }
+
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    @Override
+    @NotNull
+    public Map<String, Object> renderData(@NotNull TableInfo tableInfo) {
+        Map<String, Object> data = new HashMap<>();
+        data.put("idType", idType == null ? null : idType.toString());
+        data.put("logicDeleteFieldName", this.logicDeleteColumnName);
+        data.put("versionFieldName", this.versionColumnName);
+        data.put("activeRecord", this.activeRecord);
+        data.put("entitySerialVersionUID", this.serialVersionUID);
+        data.put("entityColumnConstant", this.columnConstant);
+        data.put("entityBuilderModel", this.chain);
+        data.put("chainModel", this.chain);
+        data.put("entityLombokModel", this.lombok);
+        data.put("entityBooleanColumnRemoveIsPrefix", this.booleanColumnRemoveIsPrefix);
+        data.put("superEntityClass", ClassUtils.getSimpleName(this.superClass));
+        return data;
+    }
+
+    public static class Builder extends BaseBuilder {
+
+        private final Entity entity = new Entity();
+
+        public Builder(StrategyConfig strategyConfig) {
+            super(strategyConfig);
+            this.entity.nameConvert = new INameConvert.DefaultNameConvert(strategyConfig);
+        }
+
+        /**
+         * 名称转换实现
+         *
+         * @param nameConvert 名称转换实现
+         * @return this
+         */
+        public Builder nameConvert(INameConvert nameConvert) {
+            this.entity.nameConvert = nameConvert;
+            return this;
+        }
+
+        /**
+         * 自定义继承的Entity类全称
+         *
+         * @param clazz 类
+         * @return this
+         */
+        public Builder superClass(@NotNull Class<?> clazz) {
+            return superClass(clazz.getName());
+        }
+
+        /**
+         * 自定义继承的Entity类全称,带包名
+         *
+         * @param superEntityClass 类全称
+         * @return this
+         */
+        public Builder superClass(String superEntityClass) {
+            this.entity.superClass = superEntityClass;
+            return this;
+        }
+
+        /**
+         * 禁用生成serialVersionUID
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder disableSerialVersionUID() {
+            this.entity.serialVersionUID = false;
+            return this;
+        }
+
+        /**
+         * 开启生成字段常量
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableColumnConstant() {
+            this.entity.columnConstant = true;
+            return this;
+        }
+
+        /**
+         * 开启链式模型
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableChainModel() {
+            this.entity.chain = true;
+            return this;
+        }
+
+        /**
+         * 开启lombok模型
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableLombok() {
+            this.entity.lombok = true;
+            return this;
+        }
+
+        /**
+         * 开启Boolean类型字段移除is前缀
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableRemoveIsPrefix() {
+            this.entity.booleanColumnRemoveIsPrefix = true;
+            return this;
+        }
+
+        /**
+         * 开启生成实体时生成字段注解
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableTableFieldAnnotation() {
+            this.entity.tableFieldAnnotationEnable = true;
+            return this;
+        }
+
+        /**
+         * 开启 ActiveRecord 模式
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableActiveRecord() {
+            this.entity.activeRecord = true;
+            return this;
+        }
+
+        /**
+         * 设置乐观锁数据库表字段名称
+         *
+         * @param versionColumnName 乐观锁数据库字段名称
+         * @return this
+         */
+        public Builder versionColumnName(String versionColumnName) {
+            this.entity.versionColumnName = versionColumnName;
+            return this;
+        }
+
+        /**
+         * 设置乐观锁实体属性字段名称
+         *
+         * @param versionPropertyName 乐观锁实体属性字段名称
+         * @return this
+         */
+        public Builder versionPropertyName(String versionPropertyName) {
+            this.entity.versionPropertyName = versionPropertyName;
+            return this;
+        }
+
+        /**
+         * 逻辑删除数据库字段名称
+         *
+         * @param logicDeleteColumnName 逻辑删除字段名称
+         * @return this
+         */
+        public Builder logicDeleteColumnName(String logicDeleteColumnName) {
+            this.entity.logicDeleteColumnName = logicDeleteColumnName;
+            return this;
+        }
+
+        /**
+         * 逻辑删除实体属性名称
+         *
+         * @param logicDeletePropertyName 逻辑删除实体属性名称
+         * @return this
+         */
+        public Builder logicDeletePropertyName(String logicDeletePropertyName) {
+            this.entity.logicDeletePropertyName = logicDeletePropertyName;
+            return this;
+        }
+
+        /**
+         * 数据库表映射到实体的命名策略
+         *
+         * @param namingStrategy 数据库表映射到实体的命名策略
+         * @return this
+         */
+        public Builder naming(NamingStrategy namingStrategy) {
+            this.entity.naming = namingStrategy;
+            return this;
+        }
+
+        /**
+         * 数据库表字段映射到实体的命名策略
+         *
+         * @param namingStrategy 数据库表字段映射到实体的命名策略
+         * @return this
+         */
+        public Builder columnNaming(NamingStrategy namingStrategy) {
+            this.entity.columnNaming = namingStrategy;
+            return this;
+        }
+
+        /**
+         * 添加父类公共字段
+         *
+         * @param superEntityColumns 父类字段(数据库字段列名)
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addSuperEntityColumns(@NotNull String... superEntityColumns) {
+            return addSuperEntityColumns(Arrays.asList(superEntityColumns));
+        }
+
+        public Builder addSuperEntityColumns(@NotNull List<String> superEntityColumnList) {
+            this.entity.superEntityColumns.addAll(superEntityColumnList);
+            return this;
+        }
+
+        /**
+         * 添加忽略字段
+         *
+         * @param ignoreColumns 需要忽略的字段(数据库字段列名)
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addIgnoreColumns(@NotNull String... ignoreColumns) {
+            return addIgnoreColumns(Arrays.asList(ignoreColumns));
+        }
+
+        public Builder addIgnoreColumns(@NotNull List<String> ignoreColumnList) {
+            this.entity.ignoreColumns.addAll(ignoreColumnList);
+            return this;
+        }
+
+        /**
+         * 添加表字段填充
+         *
+         * @param tableFills 填充字段
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addTableFills(@NotNull IFill... tableFills) {
+            return addTableFills(Arrays.asList(tableFills));
+        }
+
+        /**
+         * 添加表字段填充
+         *
+         * @param tableFillList 填充字段集合
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder addTableFills(@NotNull List<IFill> tableFillList) {
+            this.entity.tableFillList.addAll(tableFillList);
+            return this;
+        }
+
+        /**
+         * 指定生成的主键的ID类型
+         *
+         * @param idType ID类型
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder idType(IdType idType) {
+            this.entity.idType = idType;
+            return this;
+        }
+
+        /**
+         * 转换输出文件名称
+         *
+         * @param converter  转换处理
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder convertFileName(@NotNull ConverterFileName converter) {
+            this.entity.converterFileName = converter;
+            return this;
+        }
+
+        /**
+         * 格式化文件名称
+         *
+         * @param format  格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder formatFileName(String format) {
+            return convertFileName((entityName) -> String.format(format, entityName));
+        }
+
+        /**
+         * 覆盖已有文件(该方法后续会删除,替代方法为enableFileOverride方法)
+         *
+         * @see #enableFileOverride()
+         */
+        @Deprecated
+        public Builder fileOverride() {
+            LOGGER.warn("fileOverride方法后续会删除,替代方法为enableFileOverride方法");
+            this.entity.fileOverride = true;
+            return this;
+        }
+
+        /**
+         * 覆盖已有文件
+         *
+         * @since 3.5.3
+         */
+        public Builder enableFileOverride() {
+            this.entity.fileOverride = true;
+            return this;
+        }
+
+        public Entity get() {
+            String superClass = this.entity.superClass;
+            if (StringUtils.isNotBlank(superClass)) {
+                tryLoadClass(superClass).ifPresent(this.entity::convertSuperEntityColumns);
+            } else {
+                if (!this.entity.superEntityColumns.isEmpty()) {
+                    LOGGER.warn("Forgot to set entity supper class ?");
+                }
+            }
+            return this.entity;
+        }
+
+        private Optional<Class<?>> tryLoadClass(String className) {
+            try {
+                return Optional.of(ClassUtils.toClassConfident(className));
+            } catch (Exception e) {
+                //当父类实体存在类加载器的时候,识别父类实体字段,不存在的情况就只有通过指定superEntityColumns属性了。
+            }
+            return Optional.empty();
+        }
+    }
+}

+ 117 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/GeneratorBuilder.java

@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.generator.config.*;
+
+/**
+ * 生成器 Builder
+ *
+ * @author hubin 2021/02/08
+ * @since 3.5.0
+ */
+public class GeneratorBuilder {
+
+    /**
+     * 全局配置
+     *
+     * @return GlobalConfig
+     */
+    public static GlobalConfig globalConfig() {
+        return new GlobalConfig.Builder().build();
+    }
+
+    /**
+     * 全局配置 Builder
+     *
+     * @return GlobalConfig.Builder
+     */
+    public static GlobalConfig.Builder globalConfigBuilder() {
+        return new GlobalConfig.Builder();
+    }
+
+    /**
+     * 包相关的配置项
+     *
+     * @return PackageConfig
+     */
+    public static PackageConfig packageConfig() {
+        return new PackageConfig.Builder().build();
+    }
+
+    /**
+     * 包相关的配置项 Builder
+     *
+     * @return PackageConfig.Builder
+     */
+    public static PackageConfig.Builder packageConfigBuilder() {
+        return new PackageConfig.Builder();
+    }
+
+    /**
+     * 策略配置项
+     *
+     * @return StrategyConfig
+     */
+    public static StrategyConfig strategyConfig() {
+        return new StrategyConfig.Builder().build();
+    }
+
+    /**
+     * 策略配置项 Builder
+     *
+     * @return StrategyConfig.Builder
+     */
+    public static StrategyConfig.Builder strategyConfigBuilder() {
+        return new StrategyConfig.Builder();
+    }
+
+    /**
+     * 模板路径配置项
+     *
+     * @return TemplateConfig
+     */
+    public static TemplateConfig templateConfig() {
+        return new TemplateConfig.Builder().build();
+    }
+
+    /**
+     * 模板路径配置项 Builder
+     *
+     * @return TemplateConfig.Builder
+     */
+    public static TemplateConfig.Builder templateConfigBuilder() {
+        return new TemplateConfig.Builder();
+    }
+
+    /**
+     * 注入配置项
+     *
+     * @return InjectionConfig
+     */
+    public static InjectionConfig injectionConfig() {
+        return new InjectionConfig.Builder().build();
+    }
+
+    /**
+     * 注入配置项 Builder
+     *
+     * @return InjectionConfig.Builder
+     */
+    public static InjectionConfig.Builder injectionConfigBuilder() {
+        return new InjectionConfig.Builder();
+    }
+}

+ 328 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Mapper.java

@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.generator.ITemplate;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.function.ConverterFileName;
+import com.baomidou.mybatisplus.generator.util.ClassUtils;
+import org.apache.ibatis.cache.Cache;
+import org.apache.ibatis.cache.decorators.LoggingCache;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 控制器属性配置
+ *
+ * @author nieqiurong 2020/10/11.
+ * @since 3.5.0
+ */
+public class Mapper implements ITemplate {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(Mapper.class);
+
+    private Mapper() {
+    }
+
+    /**
+     * 自定义继承的Mapper类全称,带包名
+     */
+    private String superClass = ConstVal.SUPER_MAPPER_CLASS;
+
+    /**
+     * 是否添加 @Mapper 注解(默认 false)
+     *
+     * @see #mapperAnnotationClass
+     * @since 3.5.1
+     * @deprecated 3.5.4
+     */
+    @Deprecated
+    private boolean mapperAnnotation;
+
+    /**
+     * Mapper标记注解
+     *
+     * @since 3.5.3
+     */
+    private Class<? extends Annotation> mapperAnnotationClass;
+
+    /**
+     * 是否开启BaseResultMap(默认 false)
+     *
+     * @since 3.5.0
+     */
+    private boolean baseResultMap;
+
+    /**
+     * 是否开启baseColumnList(默认 false)
+     *
+     * @since 3.5.0
+     */
+    private boolean baseColumnList;
+
+    /**
+     * 转换输出Mapper文件名称
+     *
+     * @since 3.5.0
+     */
+    private ConverterFileName converterMapperFileName = (entityName -> entityName + ConstVal.MAPPER);
+
+    /**
+     * 转换输出Xml文件名称
+     *
+     * @since 3.5.0
+     */
+    private ConverterFileName converterXmlFileName = (entityName -> entityName + ConstVal.MAPPER);
+
+    /**
+     * 是否覆盖已有文件(默认 false)
+     *
+     * @since 3.5.2
+     */
+    private boolean fileOverride;
+
+    /**
+     * 设置缓存实现类
+     *
+     * @since 3.5.0
+     */
+    private Class<? extends Cache> cache;
+
+    @NotNull
+    public String getSuperClass() {
+        return superClass;
+    }
+
+    @Deprecated
+    public boolean isMapperAnnotation() {
+        return mapperAnnotationClass != null;
+    }
+
+    public boolean isBaseResultMap() {
+        return baseResultMap;
+    }
+
+    public boolean isBaseColumnList() {
+        return baseColumnList;
+    }
+
+    public ConverterFileName getConverterMapperFileName() {
+        return converterMapperFileName;
+    }
+
+    public ConverterFileName getConverterXmlFileName() {
+        return converterXmlFileName;
+    }
+
+    public Class<? extends Cache> getCache() {
+        return this.cache == null ? LoggingCache.class : this.cache;
+    }
+
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    @Override
+    @NotNull
+    public Map<String, Object> renderData(@NotNull TableInfo tableInfo) {
+        Map<String, Object> data = new HashMap<>();
+        boolean enableCache = this.cache != null;
+        data.put("enableCache", enableCache);
+        data.put("mapperAnnotation", mapperAnnotationClass != null);
+        data.put("mapperAnnotationClass", mapperAnnotationClass);
+        data.put("baseResultMap", this.baseResultMap);
+        data.put("baseColumnList", this.baseColumnList);
+        data.put("superMapperClassPackage", this.superClass);
+        if (enableCache) {
+            Class<? extends Cache> cacheClass = this.getCache();
+            data.put("cache", cacheClass);
+            data.put("cacheClassName", cacheClass.getName());
+        }
+        data.put("superMapperClass", ClassUtils.getSimpleName(this.superClass));
+        return data;
+    }
+
+    public static class Builder extends BaseBuilder {
+
+        private final Mapper mapper = new Mapper();
+
+        public Builder(StrategyConfig strategyConfig) {
+            super(strategyConfig);
+        }
+
+        /**
+         * 父类Mapper
+         *
+         * @param superClass 类名
+         * @return this
+         */
+        public Builder superClass(@NotNull String superClass) {
+            this.mapper.superClass = superClass;
+            return this;
+        }
+
+        /**
+         * 父类Mapper
+         *
+         * @param superClass 类
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder superClass(@NotNull Class<?> superClass) {
+            return superClass(superClass.getName());
+        }
+
+        /**
+         * 开启 @Mapper 注解
+         *
+         * @return this
+         * @see #mapperAnnotation(Class)
+         * @since 3.5.1
+         * @deprecated 3.5.4
+         */
+        @Deprecated
+        public Builder enableMapperAnnotation() {
+            this.mapper.mapperAnnotation = true;
+            //TODO 因为现在mybatis-plus传递mybatis-spring依赖,这里是没问题的,但后面如果考虑脱离mybatis-spring的时候就需要把这里处理掉,建议使用mapperAnnotation方法来标记自己的注解。
+            this.mapper.mapperAnnotationClass = org.apache.ibatis.annotations.Mapper.class;
+            return this;
+        }
+
+        /**
+         * 标记 Mapper 注解
+         *
+         * @param annotationClass 注解Class
+         * @return this
+         * @since 3.5.3
+         */
+        public Builder mapperAnnotation(Class<? extends Annotation> annotationClass) {
+            this.mapper.mapperAnnotationClass = annotationClass;
+            return this;
+        }
+
+        /**
+         * 开启baseResultMap
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableBaseResultMap() {
+            this.mapper.baseResultMap = true;
+            return this;
+        }
+
+        /**
+         * 开启baseColumnList
+         *
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder enableBaseColumnList() {
+            this.mapper.baseColumnList = true;
+            return this;
+        }
+
+        /**
+         * 设置缓存实现类
+         *
+         * @param cache 缓存实现
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder cache(@NotNull Class<? extends Cache> cache) {
+            this.mapper.cache = cache;
+            return this;
+        }
+
+        /**
+         * 输出Mapper文件名称转换
+         *
+         * @param converter  转换处理
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder convertMapperFileName(@NotNull ConverterFileName converter) {
+            this.mapper.converterMapperFileName = converter;
+            return this;
+        }
+
+        /**
+         * 转换Xml文件名称处理
+         *
+         * @param converter  转换处理
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder convertXmlFileName(@NotNull ConverterFileName converter) {
+            this.mapper.converterXmlFileName = converter;
+            return this;
+        }
+
+        /**
+         * 格式化Mapper文件名称
+         *
+         * @param format  格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder formatMapperFileName(@NotNull String format) {
+            return convertMapperFileName((entityName) -> String.format(format, entityName));
+        }
+
+        /**
+         * 格式化Xml文件名称
+         *
+         * @param format 格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder formatXmlFileName(@NotNull String format) {
+            return convertXmlFileName((entityName) -> String.format(format, entityName));
+        }
+
+        /**
+         * 覆盖已有文件(该方法后续会删除,替代方法为enableFileOverride方法)
+         *
+         * @see #enableFileOverride()
+         */
+        @Deprecated
+        public Builder fileOverride() {
+            LOGGER.warn("fileOverride方法后续会删除,替代方法为enableFileOverride方法");
+            this.mapper.fileOverride = true;
+            return this;
+        }
+
+        /**
+         * 覆盖已有文件
+         */
+        public Builder enableFileOverride() {
+            this.mapper.fileOverride = true;
+            return this;
+        }
+
+        @NotNull
+        public Mapper get() {
+            return this.mapper;
+        }
+    }
+}

+ 110 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/PathInfoHandler.java

@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.*;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 路径信息处理
+ *
+ * @author nieqiurong hubin
+ * @since 2020-10-06
+ * @since 3.5.0
+ */
+class PathInfoHandler {
+
+    /**
+     * 输出文件Map
+     */
+    private final Map<OutputFile, String> pathInfo = new HashMap<>();
+
+    /**
+     * 输出目录
+     */
+    private final String outputDir;
+
+    /**
+     * 包配置信息
+     */
+    private final PackageConfig packageConfig;
+
+    PathInfoHandler(GlobalConfig globalConfig, TemplateConfig templateConfig, PackageConfig packageConfig) {
+        this.outputDir = globalConfig.getOutputDir();
+        this.packageConfig = packageConfig;
+        // 设置默认输出路径
+        this.setDefaultPathInfo(globalConfig, templateConfig);
+        // 覆盖自定义路径
+        Map<OutputFile, String> pathInfo = packageConfig.getPathInfo();
+        if (CollectionUtils.isNotEmpty(pathInfo)) {
+            this.pathInfo.putAll(pathInfo);
+        }
+    }
+
+    /**
+     * 设置默认输出路径
+     *
+     * @param globalConfig   全局配置
+     * @param templateConfig 模板配置
+     */
+    private void setDefaultPathInfo(GlobalConfig globalConfig, TemplateConfig templateConfig) {
+        putPathInfo(templateConfig.getEntity(globalConfig.isKotlin()), OutputFile.entity, ConstVal.ENTITY);
+        putPathInfo(templateConfig.getMapper(), OutputFile.mapper, ConstVal.MAPPER);
+        putPathInfo(templateConfig.getXml(), OutputFile.xml, ConstVal.XML);
+        putPathInfo(templateConfig.getService(), OutputFile.service, ConstVal.SERVICE);
+        putPathInfo(templateConfig.getServiceImpl(), OutputFile.serviceImpl, ConstVal.SERVICE_IMPL);
+        putPathInfo(templateConfig.getController(), OutputFile.controller, ConstVal.CONTROLLER);
+        putPathInfo(OutputFile.parent, ConstVal.PARENT);
+    }
+
+    public Map<OutputFile, String> getPathInfo() {
+        return this.pathInfo;
+    }
+
+    private void putPathInfo(String template, OutputFile outputFile, String module) {
+        if (StringUtils.isNotBlank(template)) {
+            putPathInfo(outputFile, module);
+        }
+    }
+
+    private void putPathInfo(OutputFile outputFile, String module) {
+        pathInfo.putIfAbsent(outputFile, joinPath(outputDir, packageConfig.getPackageInfo(module)));
+    }
+
+    /**
+     * 连接路径字符串
+     *
+     * @param parentDir   路径常量字符串
+     * @param packageName 包名
+     * @return 连接后的路径
+     */
+    private String joinPath(String parentDir, String packageName) {
+        if (StringUtils.isBlank(parentDir)) {
+            parentDir = System.getProperty(ConstVal.JAVA_TMPDIR);
+        }
+        if (!StringUtils.endsWith(parentDir, File.separator)) {
+            parentDir += File.separator;
+        }
+        packageName = packageName.replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
+        return parentDir + packageName;
+    }
+}

+ 231 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Service.java

@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.builder;
+
+import com.baomidou.mybatisplus.generator.ITemplate;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.function.ConverterFileName;
+import com.baomidou.mybatisplus.generator.util.ClassUtils;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Service属性配置
+ *
+ * @author nieqiurong 2020/10/11.
+ * @since 3.5.0
+ */
+public class Service implements ITemplate {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(Service.class);
+
+    private Service() {
+    }
+
+    /**
+     * 自定义继承的Service类全称,带包名
+     */
+    private String superServiceClass = ConstVal.SUPER_SERVICE_CLASS;
+
+    /**
+     * 自定义继承的ServiceImpl类全称,带包名
+     */
+    private String superServiceImplClass = ConstVal.SUPER_SERVICE_IMPL_CLASS;
+
+    @NotNull
+    public String getSuperServiceClass() {
+        return superServiceClass;
+    }
+
+    @NotNull
+    public String getSuperServiceImplClass() {
+        return superServiceImplClass;
+    }
+
+    /**
+     * 转换输出Service文件名称
+     *
+     * @since 3.5.0
+     */
+    private ConverterFileName converterServiceFileName = (entityName -> "I" + entityName + ConstVal.SERVICE);
+
+    /**
+     * 转换输出ServiceImpl文件名称
+     *
+     * @since 3.5.0
+     */
+    private ConverterFileName converterServiceImplFileName = (entityName -> entityName + ConstVal.SERVICE_IMPL);
+
+    /**
+     * 是否覆盖已有文件(默认 false)
+     *
+     * @since 3.5.2
+     */
+    private boolean fileOverride;
+
+    @NotNull
+    public ConverterFileName getConverterServiceFileName() {
+        return converterServiceFileName;
+    }
+
+    @NotNull
+    public ConverterFileName getConverterServiceImplFileName() {
+        return converterServiceImplFileName;
+    }
+
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    @Override
+    @NotNull
+    public Map<String, Object> renderData(@NotNull TableInfo tableInfo) {
+        Map<String, Object> data = new HashMap<>();
+        data.put("superServiceClassPackage", this.superServiceClass);
+        data.put("superServiceClass", ClassUtils.getSimpleName(this.superServiceClass));
+        data.put("superServiceImplClassPackage", this.superServiceImplClass);
+        data.put("superServiceImplClass", ClassUtils.getSimpleName(this.superServiceImplClass));
+        return data;
+    }
+
+    public static class Builder extends BaseBuilder {
+
+        private final Service service = new Service();
+
+        public Builder(@NotNull StrategyConfig strategyConfig) {
+            super(strategyConfig);
+        }
+
+        /**
+         * Service接口父类
+         *
+         * @param clazz 类
+         * @return this
+         */
+        public Builder superServiceClass(@NotNull Class<?> clazz) {
+            return superServiceClass(clazz.getName());
+        }
+
+        /**
+         * Service接口父类
+         *
+         * @param superServiceClass 类名
+         * @return this
+         */
+        public Builder superServiceClass(@NotNull String superServiceClass) {
+            this.service.superServiceClass = superServiceClass;
+            return this;
+        }
+
+        /**
+         * Service实现类父类
+         *
+         * @param clazz 类
+         * @return this
+         */
+        public Builder superServiceImplClass(@NotNull Class<?> clazz) {
+            return superServiceImplClass(clazz.getName());
+        }
+
+        /**
+         * Service实现类父类
+         *
+         * @param superServiceImplClass 类名
+         * @return this
+         */
+        public Builder superServiceImplClass(@NotNull String superServiceImplClass) {
+            this.service.superServiceImplClass = superServiceImplClass;
+            return this;
+        }
+
+        /**
+         * 转换输出service接口文件名称
+         *
+         * @param converter  转换处理
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder convertServiceFileName(@NotNull ConverterFileName converter) {
+            this.service.converterServiceFileName = converter;
+            return this;
+        }
+
+        /**
+         * 转换输出service实现类文件名称
+         *
+         * @param converter  转换处理
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder convertServiceImplFileName(@NotNull ConverterFileName converter) {
+            this.service.converterServiceImplFileName = converter;
+            return this;
+        }
+
+        /**
+         * 格式化service接口文件名称
+         *
+         * @param format  格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder formatServiceFileName(@NotNull String format) {
+            return convertServiceFileName((entityName) -> String.format(format, entityName));
+        }
+
+        /**
+         * 格式化service实现类文件名称
+         *
+         * @param format  格式
+         * @return this
+         * @since 3.5.0
+         */
+        public Builder formatServiceImplFileName(@NotNull String format) {
+            return convertServiceImplFileName((entityName) -> String.format(format, entityName));
+        }
+
+        /**
+         * 覆盖已有文件(该方法后续会删除,替代方法为enableFileOverride方法)
+         *
+         * @see #enableFileOverride()
+         */
+        @Deprecated
+        public Builder fileOverride() {
+            LOGGER.warn("fileOverride方法后续会删除,替代方法为enableFileOverride方法");
+            this.service.fileOverride = true;
+            return this;
+        }
+
+        /**
+         * 覆盖已有文件
+         */
+        public Builder enableFileOverride() {
+            this.service.fileOverride = true;
+            return this;
+        }
+
+        @NotNull
+        public Service get() {
+            return this.service;
+        }
+    }
+}

+ 19 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/package-info.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 代码生成器,构建类
+ */
+package com.baomidou.mybatisplus.generator.config.builder;

+ 87 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/ClickHouseTypeConvert.java

@@ -0,0 +1,87 @@
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import org.jetbrains.annotations.NotNull;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * ClickHouse 字段类型转换
+ *
+ * @author urzeye
+ * @date 2021年9月12日
+ */
+public class ClickHouseTypeConvert implements ITypeConvert {
+
+    public static final ClickHouseTypeConvert INSTANCE = new ClickHouseTypeConvert();
+
+    static final String[] INTEGER_TYPE = new String[]{
+        "intervalyear", "intervalquarter", "intervalmonth", "intervalweek",
+        "intervalday", "intervalhour", "intervalminute", "intervalsecond",
+        "uint16", "uint8", "int16", "int8", "int32"
+    };
+
+    static final String[] BIGINTEGER_TYPE = new String[]{
+        "uint256", "uint128", "uint64", "int256", "int128"
+    };
+
+    static final String[] BIGDECIMAL_TYPE = new String[]{
+        "decimal32", "decimal64", "decimal128", "decimal256", "decimal"
+    };
+
+    static final String[] LONG_TYPE = new String[]{
+        "int64", "uint32"
+    };
+
+    static final String[] STRING_TYPE = new String[]{
+        "uuid", "char", "varchar", "text", "tinytext", "longtext", "blob", "tinyblob", "mediumblob", "longblob",
+        "enum8", "enum16", "ipv4", "ipv6", "string", "fixedstring", "nothing", "nested", "tuple", "aggregatefunction", "unknown"
+    };
+
+
+    @Override
+    public IColumnType processTypeConvert(@NotNull GlobalConfig globalConfig, @NotNull String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny(INTEGER_TYPE).then(INTEGER))
+            .test(containsAny(BIGINTEGER_TYPE).then(BIG_INTEGER))
+            .test(containsAny(BIGDECIMAL_TYPE).then(BIG_DECIMAL))
+            .test(containsAny(LONG_TYPE).then(LONG))
+            .test(contains("float32").then(FLOAT))
+            .test(contains("float64").then(DOUBLE))
+            .test(contains("map").then(MAP))
+            .test(contains("array").then(OBJECT))
+            .test(containsAny("date", "datetime", "datetime64").then(t -> toDateType(globalConfig, fieldType)))
+            .test(containsAny(STRING_TYPE).then(STRING))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param type   类型
+     * @return 返回对应的列类型
+     */
+    public static IColumnType toDateType(GlobalConfig config, String type) {
+        switch (config.getDateType()) {
+            case SQL_PACK:
+                if ("date".equals(type)) {
+                    return DbColumnType.DATE_SQL;
+                }
+                return DbColumnType.TIMESTAMP;
+            case TIME_PACK:
+                if ("date".equals(type)) {
+                    return DbColumnType.LOCAL_DATE;
+                }
+                return DbColumnType.LOCAL_DATE_TIME;
+            default:
+                return DbColumnType.DATE;
+        }
+    }
+
+}

+ 56 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DB2TypeConvert.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * DB2 字段类型转换
+ *
+ * @author zhanyao, hanchunlin
+ * @since 2018-05-16
+ */
+public class DB2TypeConvert implements ITypeConvert {
+    public static final DB2TypeConvert INSTANCE = new DB2TypeConvert();
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "text", "json", "enum").then(STRING))
+            .test(contains("bigint").then(LONG))
+            .test(contains("smallint").then(BASE_SHORT))
+            .test(contains("int").then(INTEGER))
+            .test(containsAny("date", "time", "year").then(DATE))
+            .test(contains("bit").then(BOOLEAN))
+            .test(contains("decimal").then(BIG_DECIMAL))
+            .test(contains("clob").then(CLOB))
+            .test(contains("blob").then(BLOB))
+            .test(contains("binary").then(BYTE_ARRAY))
+            .test(contains("float").then(FLOAT))
+            .test(contains("double").then(DOUBLE))
+            .or(STRING);
+    }
+
+}

+ 82 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DmTypeConvert.java

@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * DM 字段类型转换
+ *
+ * @author halower, hanchunlin, daiby
+ * @since 2019-06-27
+ */
+public class DmTypeConvert implements ITypeConvert {
+    public static final DmTypeConvert INSTANCE = new DmTypeConvert();
+
+    /**
+     * 字符数据类型: CHAR,CHARACTER,VARCHAR
+     * <p>
+     * 数值数据类型: NUMBER,NUMERIC,DECIMAL,DEC,MONEY,BIT,BOOL,BOOLEAN,INTEGER,INT,BIGINT,TINYINT,BYTE,SMALLINT,BINARY,
+     * VARBINARY
+     * <p>
+     * 近似数值数据类型: FLOAT
+     * <p>
+     * DOUBLE, DOUBLE PRECISION,REAL
+     * <p>
+     * 日期时间数据类型
+     * <p>
+     * 多媒体数据类型: TEXT,LONGVARCHAR,CLOB,BLOB,IMAGE
+     *
+     * @param config    全局配置
+     * @param fieldType 字段类型
+     * @return 对应的数据类型
+     * @inheritDoc
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "text").then(STRING))
+            .test(contains("number").then(DmTypeConvert::toNumberType))
+            .test(containsAny("numeric", "dec", "money").then(BIG_DECIMAL))
+            .test(containsAny("bit", "bool").then(BOOLEAN))
+            .test(contains("bigint").then(BIG_INTEGER))
+            .test(containsAny("int", "byte").then(INTEGER))
+            .test(contains("binary").then(BYTE_ARRAY))
+            .test(contains("float").then(FLOAT))
+            .test(containsAny("double", "real").then(DOUBLE))
+            .test(containsAny("date", "time").then(DATE))
+            .test(contains("clob").then(CLOB))
+            .test(contains("blob").then(BLOB))
+            .test(contains("image").then(BYTE_ARRAY))
+            .or(STRING);
+    }
+
+    private static IColumnType toNumberType(String typeName) {
+        if (typeName.matches("number\\([0-9]\\)")) {
+            return DbColumnType.INTEGER;
+        } else if (typeName.matches("number\\(1[0-8]\\)")) {
+            return DbColumnType.LONG;
+        }
+        return DbColumnType.BIG_DECIMAL;
+    }
+}

+ 89 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/FirebirdTypeConvert.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * MYSQL 数据库字段类型转换
+ *
+ * @author hubin, hanchunlin
+ * @since 2017-01-20
+ */
+public class FirebirdTypeConvert implements ITypeConvert {
+    public static final FirebirdTypeConvert INSTANCE = new FirebirdTypeConvert();
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("cstring", "text").then(STRING))
+            .test(contains("short").then(SHORT))
+            .test(contains("long").then(LONG))
+            .test(contains("float").then(FLOAT))
+            .test(contains("double").then(DOUBLE))
+            .test(contains("blob").then(BLOB))
+            .test(contains("int64").then(LONG))
+            .test(containsAny("date", "time", "year").then(t -> toDateType(config, t)))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param type   类型
+     * @return 返回对应的列类型
+     */
+    public static IColumnType toDateType(GlobalConfig config, String type) {
+        switch (config.getDateType()) {
+            case ONLY_DATE:
+                return DbColumnType.DATE;
+            case SQL_PACK:
+                switch (type) {
+                    case "date":
+                    case "year":
+                        return DbColumnType.DATE_SQL;
+                    case "time":
+                        return DbColumnType.TIME;
+                    default:
+                        return DbColumnType.TIMESTAMP;
+                }
+            case TIME_PACK:
+                switch (type) {
+                    case "date":
+                        return DbColumnType.LOCAL_DATE;
+                    case "time":
+                        return DbColumnType.LOCAL_TIME;
+                    case "year":
+                        return DbColumnType.YEAR;
+                    default:
+                        return DbColumnType.LOCAL_DATE_TIME;
+                }
+        }
+        return STRING;
+    }
+
+}

+ 89 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/KingbaseESTypeConvert.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DateType;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * KingbaseES 字段类型转换
+ *
+ * @author kingbase, hanchunlin
+ * @since 2019-10-12
+ */
+public class KingbaseESTypeConvert implements ITypeConvert {
+    public static final KingbaseESTypeConvert INSTANCE = new KingbaseESTypeConvert();
+
+    /**
+     * @param globalConfig 全局配置
+     * @param fieldType    字段类型
+     * @return 返回对应的字段类型
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "text", "json", "enum").then(STRING))
+            .test(contains("bigint").then(LONG))
+            .test(contains("int").then(INTEGER))
+            .test(containsAny("date", "time").then(p -> toDateType(globalConfig, p)))
+            .test(containsAny("bit", "boolean").then(BOOLEAN))
+            .test(containsAny("decimal", "numeric").then(BIG_DECIMAL))
+            .test(contains("clob").then(CLOB))
+            .test(contains("blob").then(BYTE_ARRAY))
+            .test(contains("float").then(FLOAT))
+            .test(contains("double").then(DOUBLE))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param type   类型
+     * @return 返回对应的列类型
+     */
+    private IColumnType toDateType(GlobalConfig config, String type) {
+        DateType dateType = config.getDateType();
+        if (dateType == DateType.SQL_PACK) {
+            switch (type) {
+                case "date":
+                    return DATE_SQL;
+                case "time":
+                    return TIME;
+                default:
+                    return TIMESTAMP;
+            }
+        } else if (dateType == DateType.TIME_PACK) {
+            switch (type) {
+                case "date":
+                    return LOCAL_DATE;
+                case "time":
+                    return LOCAL_TIME;
+                default:
+                    return LOCAL_DATE_TIME;
+            }
+        }
+        return DbColumnType.DATE;
+    }
+
+}

+ 94 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/MySqlTypeConvert.java

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * MYSQL 数据库字段类型转换
+ * bit类型数据转换 bit(1) -> Boolean类型  bit(2->64)  -> Byte类型
+ * @author hubin, hanchunlin, xiaoliang
+ * @since 2017-01-20
+ */
+public class MySqlTypeConvert implements ITypeConvert {
+    public static final MySqlTypeConvert INSTANCE = new MySqlTypeConvert();
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "text", "json", "enum").then(STRING))
+            .test(contains("bigint").then(LONG))
+            .test(containsAny("tinyint(1)", "bit(1)").then(BOOLEAN))
+            .test(contains("bit").then(BYTE))
+            .test(contains("int").then(INTEGER))
+            .test(contains("decimal").then(BIG_DECIMAL))
+            .test(contains("clob").then(CLOB))
+            .test(contains("blob").then(BLOB))
+            .test(contains("binary").then(BYTE_ARRAY))
+            .test(contains("float").then(FLOAT))
+            .test(contains("double").then(DOUBLE))
+            .test(containsAny("date", "time", "year").then(t -> toDateType(config, t)))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param type   类型
+     * @return 返回对应的列类型
+     */
+    public static IColumnType toDateType(GlobalConfig config, String type) {
+        String dateType = type.replaceAll("\\(\\d+\\)", "");
+        switch (config.getDateType()) {
+            case ONLY_DATE:
+                return DbColumnType.DATE;
+            case SQL_PACK:
+                switch (dateType) {
+                    case "date":
+                    case "year":
+                        return DbColumnType.DATE_SQL;
+                    case "time":
+                        return DbColumnType.TIME;
+                    default:
+                        return DbColumnType.TIMESTAMP;
+                }
+            case TIME_PACK:
+                switch (dateType) {
+                    case "date":
+                        return DbColumnType.LOCAL_DATE;
+                    case "time":
+                        return DbColumnType.LOCAL_TIME;
+                    case "year":
+                        return DbColumnType.YEAR;
+                    default:
+                        return DbColumnType.LOCAL_DATE_TIME;
+                }
+        }
+        return STRING;
+    }
+
+}

+ 96 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OracleTypeConvert.java

@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * Oracle 数据库生成对应实体类时字段类型转换,跟据 Oracle 中的数据类型,返回对应的 Java 类型
+ *
+ * @author hubin, hanchunlin
+ * @since 2017-01-20
+ */
+public class OracleTypeConvert implements ITypeConvert {
+    public static final OracleTypeConvert INSTANCE = new OracleTypeConvert();
+
+    /**
+     * 处理类型转换
+     *
+     * @param config    全局配置
+     * @param fieldType 字段类型
+     * @return 返回的对应的列类型
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "clob").then(STRING))
+            .test(containsAny("date", "timestamp").then(p -> toDateType(config)))
+            .test(contains("number").then(OracleTypeConvert::toNumberType))
+            .test(contains("float").then(FLOAT))
+            .test(contains("blob").then(BLOB))
+            .test(containsAny("binary", "raw").then(BYTE_ARRAY))
+            .or(STRING);
+    }
+
+    /**
+     * 将对应的类型名称转换为对应的 java 类类型
+     * <p>
+     * String.valueOf(Integer.MAX_VALUE).length() == 10
+     * Integer 不一定能装下 10 位的数字
+     * <p>
+     * String.valueOf(Long.MAX_VALUE).length() == 19
+     * Long 不一定能装下 19 位的数字
+     *
+     * @param typeName 类型名称
+     * @return 返回列类型
+     */
+    private static IColumnType toNumberType(String typeName) {
+        if (typeName.matches("number\\([0-9]\\)")) {
+            return DbColumnType.INTEGER;
+        } else if (typeName.matches("number\\(1[0-8]\\)")) {
+            return DbColumnType.LONG;
+        }
+        return DbColumnType.BIG_DECIMAL;
+    }
+
+    /**
+     * 当前时间为字段类型,根据全局配置返回对应的时间类型
+     *
+     * @param config 全局配置
+     * @return 时间类型
+     * @see GlobalConfig#getDateType()
+     */
+    protected static IColumnType toDateType(GlobalConfig config) {
+        switch (config.getDateType()) {
+            case ONLY_DATE:
+                return DbColumnType.DATE;
+            case SQL_PACK:
+                return DbColumnType.TIMESTAMP;
+            case TIME_PACK:
+                return DbColumnType.LOCAL_DATE_TIME;
+            default:
+                return STRING;
+        }
+    }
+
+}

+ 89 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OscarTypeConvert.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DateType;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * KingbaseES 字段类型转换
+ *
+ * @author kingbase, hanchunlin
+ * @since 2019-10-12
+ */
+public class OscarTypeConvert implements ITypeConvert {
+    public static final OscarTypeConvert INSTANCE = new OscarTypeConvert();
+
+    /**
+     * @param globalConfig 全局配置
+     * @param fieldType    字段类型
+     * @return 返回对应的字段类型
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("CHARACTER", "char", "varchar", "text", "character varying").then(STRING))
+            .test(containsAny("bigint", "int8").then(LONG))
+            .test(containsAny("int", "int1", "int2", "int3", "int4", "tinyint", "integer").then(INTEGER))
+            .test(containsAny("date", "time", "timestamp").then(p -> toDateType(globalConfig, p)))
+            .test(containsAny("bit", "boolean").then(BOOLEAN))
+            .test(containsAny("decimal", "numeric", "number").then(BIG_DECIMAL))
+            .test(contains("clob").then(CLOB))
+            .test(contains("blob").then(BYTE_ARRAY))
+            .test(contains("float").then(FLOAT))
+            .test(containsAny("double", "real", "float4", "float8").then(DOUBLE))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param type   类型
+     * @return 返回对应的列类型
+     */
+    private IColumnType toDateType(GlobalConfig config, String type) {
+        DateType dateType = config.getDateType();
+        if (dateType == DateType.SQL_PACK) {
+            switch (type) {
+                case "date":
+                    return DATE_SQL;
+                case "time":
+                    return TIME;
+                default:
+                    return TIMESTAMP;
+            }
+        } else if (dateType == DateType.TIME_PACK) {
+            switch (type) {
+                case "date":
+                    return LOCAL_DATE;
+                case "time":
+                    return LOCAL_TIME;
+                default:
+                    return LOCAL_DATE_TIME;
+            }
+        }
+        return DbColumnType.DATE;
+    }
+
+}

+ 86 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/PostgreSqlTypeConvert.java

@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * PostgreSQL 字段类型转换
+ *
+ * @author hubin, hanchunlin
+ * @since 2017-01-20
+ */
+public class PostgreSqlTypeConvert implements ITypeConvert {
+    public static final PostgreSqlTypeConvert INSTANCE = new PostgreSqlTypeConvert();
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "text", "json", "enum").then(STRING))
+            .test(contains("bigint").then(LONG))
+            .test(contains("int").then(INTEGER))
+            .test(containsAny("date", "time").then(t -> toDateType(config, t)))
+            .test(contains("bit").then(BOOLEAN))
+            .test(containsAny("decimal", "numeric").then(BIG_DECIMAL))
+            .test(contains("bytea").then(BYTE_ARRAY))
+            .test(contains("float").then(FLOAT))
+            .test(contains("double").then(DOUBLE))
+            .test(contains("boolean").then(BOOLEAN))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param type   类型
+     * @return 返回对应的列类型
+     */
+    public static IColumnType toDateType(GlobalConfig config, String type) {
+        switch (config.getDateType()) {
+            case SQL_PACK:
+                switch (type) {
+                    case "date":
+                        return DbColumnType.DATE_SQL;
+                    case "time":
+                        return DbColumnType.TIME;
+                    default:
+                        return DbColumnType.TIMESTAMP;
+                }
+            case TIME_PACK:
+                switch (type) {
+                    case "date":
+                        return DbColumnType.LOCAL_DATE;
+                    case "time":
+                        return DbColumnType.LOCAL_TIME;
+                    default:
+                        return DbColumnType.LOCAL_DATE_TIME;
+                }
+            default:
+                return DbColumnType.DATE;
+        }
+    }
+}

+ 99 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqlServerTypeConvert.java

@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.BIG_DECIMAL;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.BOOLEAN;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.BYTE_ARRAY;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.DATE;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.DATE_SQL;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.DOUBLE;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.FLOAT;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.INTEGER;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.LOCAL_DATE;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.LOCAL_DATE_TIME;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.LOCAL_TIME;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.LONG;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.STRING;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.TIME;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.TIMESTAMP;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+/**
+ * SQLServer 字段类型转换
+ *
+ * @author hubin, hanchunlin
+ * @since 2017-01-20
+ */
+public class SqlServerTypeConvert implements ITypeConvert {
+
+    public static final SqlServerTypeConvert INSTANCE = new SqlServerTypeConvert();
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(containsAny("char", "xml", "text").then(STRING))
+            .test(contains("bigint").then(LONG))
+            .test(contains("int").then(INTEGER))
+            .test(containsAny("date", "time").then(t -> toDateType(config, t)))
+            .test(contains("bit").then(BOOLEAN))
+            .test(containsAny("decimal", "numeric").then(DOUBLE))
+            .test(contains("money").then(BIG_DECIMAL))
+            .test(containsAny("binary", "image").then(BYTE_ARRAY))
+            .test(containsAny("float", "real").then(FLOAT))
+            .or(STRING);
+    }
+
+    /**
+     * 转换为日期类型
+     *
+     * @param config 配置信息
+     * @param fieldType   类型
+     * @return 返回对应的列类型
+     */
+    public static IColumnType toDateType(GlobalConfig config, String fieldType) {
+        switch (config.getDateType()) {
+            case SQL_PACK:
+                switch (fieldType) {
+                    case "date":
+                        return DATE_SQL;
+                    case "time":
+                        return TIME;
+                    default:
+                        return TIMESTAMP;
+                }
+            case TIME_PACK:
+                switch (fieldType) {
+                    case "date":
+                        return LOCAL_DATE;
+                    case "time":
+                        return LOCAL_TIME;
+                    default:
+                        return LOCAL_DATE_TIME;
+                }
+            default:
+                return DATE;
+        }
+    }
+}

+ 57 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqliteTypeConvert.java

@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+import static com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert.toDateType;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.contains;
+import static com.baomidou.mybatisplus.generator.config.converts.TypeConverts.containsAny;
+import static com.baomidou.mybatisplus.generator.config.rules.DbColumnType.*;
+
+/**
+ * SQLite 字段类型转换
+ *
+ * @author chen_wj, hanchunlin
+ * @since 2019-05-08
+ */
+public class SqliteTypeConvert implements ITypeConvert {
+    public static final SqliteTypeConvert INSTANCE = new SqliteTypeConvert();
+
+    /**
+     * @inheritDoc
+     * @see MySqlTypeConvert#toDateType(GlobalConfig, String)
+     */
+    @Override
+    public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
+        return TypeConverts.use(fieldType)
+            .test(contains("bigint").then(LONG))
+            .test(containsAny("tinyint(1)", "boolean").then(BOOLEAN))
+            .test(contains("int").then(INTEGER))
+            .test(containsAny("text", "char", "enum").then(STRING))
+            .test(containsAny("decimal", "numeric").then(BIG_DECIMAL))
+            .test(contains("clob").then(CLOB))
+            .test(contains("blob").then(BLOB))
+            .test(contains("float").then(FLOAT))
+            .test(contains("double").then(DOUBLE))
+            .test(containsAny("date", "time", "year").then(t -> toDateType(config, t)))
+            .or(DbColumnType.STRING);
+    }
+
+}

+ 100 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/TypeConverts.java

@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.converts.select.BranchBuilder;
+import com.baomidou.mybatisplus.generator.config.converts.select.Selector;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+
+/**
+ * 该注册器负责注册并查询类型注册器
+ *
+ * @author nieqiuqiu, hanchunlin
+ * @since 3.3.1
+ */
+public class TypeConverts {
+
+    /**
+     * 查询数据库类型对应的类型转换器
+     *
+     * @param dbType 数据库类型
+     * @return 返回转换器
+     */
+    public static ITypeConvert getTypeConvert(DbType dbType) {
+        switch (dbType) {
+            case ORACLE:
+                return OracleTypeConvert.INSTANCE;
+            case DB2:
+                return DB2TypeConvert.INSTANCE;
+            case DM:
+            case GAUSS:
+                return DmTypeConvert.INSTANCE;
+            case KINGBASE_ES:
+                return KingbaseESTypeConvert.INSTANCE;
+            case OSCAR:
+                return OscarTypeConvert.INSTANCE;
+            case MYSQL:
+            case MARIADB:
+                return MySqlTypeConvert.INSTANCE;
+            case POSTGRE_SQL:
+                return PostgreSqlTypeConvert.INSTANCE;
+            case SQLITE:
+                return SqliteTypeConvert.INSTANCE;
+            case SQL_SERVER:
+                return SqlServerTypeConvert.INSTANCE;
+            case FIREBIRD:
+                return FirebirdTypeConvert.INSTANCE;
+            case CLICK_HOUSE:
+                return ClickHouseTypeConvert.INSTANCE;
+        }
+        return null;
+    }
+
+    /**
+     * 使用指定参数构建一个选择器
+     *
+     * @param param 参数
+     * @return 返回选择器
+     */
+    static Selector<String, IColumnType> use(String param) {
+        return new Selector<>(param.toLowerCase());
+    }
+
+    /**
+     * 这个分支构建器用于构建用于支持 {@link String#contains(CharSequence)} 的分支
+     *
+     * @param value 分支的值
+     * @return 返回分支构建器
+     * @see #containsAny(CharSequence...)
+     */
+    static BranchBuilder<String, IColumnType> contains(CharSequence value) {
+        return BranchBuilder.of(s -> s.contains(value));
+    }
+
+    /**
+     * @see #contains(CharSequence)
+     */
+    static BranchBuilder<String, IColumnType> containsAny(CharSequence... values) {
+        return BranchBuilder.of(s -> {
+            for (CharSequence value : values) {
+                if (s.contains(value)) return true;
+            }
+            return false;
+        });
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/package-info.java

@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.converts;

+ 49 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/Branch.java

@@ -0,0 +1,49 @@
+package com.baomidou.mybatisplus.generator.config.converts.select;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * 分支提供者
+ *
+ * @author hanchunlin
+ * Created at 2020/6/11 17:19
+ * @see BranchBuilder
+ */
+public interface Branch<P, T> {
+
+    /**
+     * @return 分支进入条件
+     */
+    Predicate<P> tester();
+
+    /**
+     * @return 值工厂
+     */
+    Function<P, T> factory();
+
+    /**
+     * 工厂方法,快速创建分支
+     *
+     * @param tester  测试器
+     * @param factory 值工厂
+     * @param <P>     参数类型
+     * @param <T>     值类型
+     * @return 返回一个新的分支
+     */
+    static <P, T> Branch<P, T> of(Predicate<P> tester, Function<P, T> factory) {
+        return new Branch<P, T>() {
+
+            @Override
+            public Predicate<P> tester() {
+                return tester;
+            }
+
+            @Override
+            public Function<P, T> factory() {
+                return factory;
+            }
+
+        };
+    }
+}

+ 44 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/BranchBuilder.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.generator.config.converts.select;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * 分支构建者
+ *
+ * @author hanchunlin
+ * Created at 2020/6/11 17:22
+ */
+public interface BranchBuilder<P, T> {
+
+    /**
+     * 使用一个值工厂构造出一个分支
+     *
+     * @param factory 值工厂
+     * @return 返回分支
+     */
+    Branch<P, T> then(Function<P, T> factory);
+
+    /**
+     * 从值构建出一个分支
+     *
+     * @param value 值
+     * @return 返回一个分支
+     */
+    default Branch<P, T> then(T value) {
+        return then(p -> value);
+    }
+
+    /**
+     * 工厂函数,用于创建分支构建者
+     *
+     * @param tester 测试器
+     * @param <P>    参数类型
+     * @param <T>    返回值类型
+     * @return 返回一个分支创建者
+     */
+    static <P, T> BranchBuilder<P, T> of(Predicate<P> tester) {
+        return factory -> Branch.of(tester, factory);
+    }
+
+}

+ 95 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/Selector.java

@@ -0,0 +1,95 @@
+package com.baomidou.mybatisplus.generator.config.converts.select;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * 分支结果选择器
+ * <p>
+ * 当前选择器会从给定的分支中选择第一个匹配的分支,并返回其结果
+ * <p>
+ * 一旦结果被选择,其他的分支将不再被调用
+ *
+ * @author hanchunlin
+ * Created at 2020/6/11 16:55
+ */
+public class Selector<P, T> {
+    private boolean selected = false;
+    private Function<P, T> factory;
+
+    /**
+     * 选择器参数,该参数会在进行条件判断和结果获取时会被当做条件传入
+     */
+    private final P param;
+
+    /**
+     * @param param 参数
+     */
+    public Selector(P param) {
+        this.param = param;
+    }
+
+    /**
+     * 使用指定的参数创建选择器
+     *
+     * @param param 参数
+     * @param <P>   参数类型
+     * @param <T>   返回值类型
+     * @return 返回新的选择器
+     */
+    public static <P, T> Selector<P, T> param(P param) {
+        return new Selector<>(param);
+    }
+
+    /**
+     * 传入一个新的分支,如果这个分支满足条件
+     *
+     * @param branch 则当前选择器将接受当前分支的结果并完成
+     * @return 选择器自身
+     */
+    public Selector<P, T> test(Branch<P, T> branch) {
+        if (!selected) {
+            boolean pass = branch.tester().test(param);
+            if (pass) {
+                selected = true;
+                factory = branch.factory();
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 获取结果,如果当前选择器没有击中任何条件分支,则从给定的提供者中获取结果;
+     * 否则将使用当前选择器选中的分支
+     *
+     * @param supplier 默认值提供者
+     * @return 如果有分支被击中,则返回分支值,否则返回参数提供的值
+     */
+    public T or(Supplier<T> supplier) {
+        return selected ? this.factory.apply(param) : supplier.get();
+    }
+
+    /**
+     * @param t 给定默认值
+     * @return 如果有分支被击中,则返回分支值,否则返回参数
+     * @see #or(Supplier)
+     */
+    public T or(T t) {
+        return or(() -> t);
+    }
+
+    /**
+     * 当前选择器是否已经选择分支
+     *
+     * @return 如果已经存在分支被击中,则返回 true;否则返回 false
+     */
+    public boolean isSelected() {
+        return selected;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Selector{success=%s}", selected);
+    }
+
+}

+ 19 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/package-info.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 代码生成器,配置相关类
+ */
+package com.baomidou.mybatisplus.generator.config;

+ 52 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/LikeTable.java

@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.po;
+
+import com.baomidou.mybatisplus.core.enums.SqlLike;
+import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
+
+/**
+ * 表名拼接
+ *
+ * @author nieqiuqiu
+ * @date 2019-11-26
+ * @since 3.3.0
+ */
+public class LikeTable {
+
+    private final String value;
+
+    private SqlLike like = SqlLike.DEFAULT;
+
+    public LikeTable(String value) {
+        this.value = value;
+    }
+
+    public LikeTable(String value, SqlLike like) {
+        this.value = value;
+        this.like = like;
+    }
+
+    @Override
+    public String toString() {
+        return getValue();
+    }
+
+    public String getValue() {
+        return SqlUtils.concatLike(this.value, like);
+    }
+
+}

+ 448 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableField.java

@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.po;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.IKeyWordsHandler;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.builder.Entity;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.fill.Column;
+import com.baomidou.mybatisplus.generator.fill.Property;
+import com.baomidou.mybatisplus.generator.jdbc.DatabaseMetaDataWrapper;
+import org.apache.ibatis.type.JdbcType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+/**
+ * 表字段信息
+ *
+ * @author YangHu
+ * @since 2016-12-03
+ */
+public class TableField {
+
+    /**
+     * 是否做注解转换
+     */
+    private boolean convert;
+
+    /**
+     * 是否主键
+     */
+    private boolean keyFlag;
+
+    /**
+     * 主键是否为自增类型
+     */
+    private boolean keyIdentityFlag;
+
+    /**
+     * 字段名称
+     */
+    private String name;
+
+    /**
+     * 字段类型(已弃用,使用 {@link #columnType} 代替)
+     */
+    @Deprecated
+    private String type;
+
+    /**
+     * 属性名称
+     */
+    private String propertyName;
+
+    /**
+     * 字段类型
+     */
+    private IColumnType columnType;
+
+    /**
+     * 字段注释
+     */
+    private String comment;
+
+    /**
+     * 填充
+     */
+    private String fill;
+
+    /**
+     * 是否关键字
+     *
+     * @since 3.3.2
+     */
+    private boolean keyWords;
+
+    /**
+     * 数据库字段(关键字含转义符号)
+     *
+     * @since 3.3.2
+     */
+    private String columnName;
+
+    /**
+     * 自定义查询字段列表
+     */
+    private Map<String, Object> customMap;
+
+    /**
+     * 字段元数据信息
+     *
+     * @since 3.5.0
+     */
+    private MetaInfo metaInfo;
+
+    /**
+     * 实体属性配置
+     */
+    private final Entity entity;
+
+    /**
+     * 数据库配置
+     */
+    private final DataSourceConfig dataSourceConfig;
+
+    /**
+     * 全局配置
+     */
+    private final GlobalConfig globalConfig;
+
+    /**
+     * 构造方法
+     *
+     * @param configBuilder 配置构建
+     * @param name          数据库字段名称
+     * @since 3.5.0
+     */
+    public TableField(@NotNull ConfigBuilder configBuilder, @NotNull String name) {
+        this.name = name;
+        this.columnName = name;
+        this.entity = configBuilder.getStrategyConfig().entity();
+        this.dataSourceConfig = configBuilder.getDataSourceConfig();
+        this.globalConfig = configBuilder.getGlobalConfig();
+    }
+
+    /**
+     * 设置属性名称
+     *
+     * @param propertyName 属性名
+     * @param columnType   字段类型
+     * @return this
+     * @since 3.5.0
+     */
+    public TableField setPropertyName(@NotNull String propertyName, @NotNull IColumnType columnType) {
+        this.columnType = columnType;
+        if (entity.isBooleanColumnRemoveIsPrefix()
+            && "boolean".equalsIgnoreCase(this.getPropertyType()) && propertyName.startsWith("is")) {
+            this.convert = true;
+            this.propertyName = StringUtils.removePrefixAfterPrefixToLower(propertyName, 2);
+            return this;
+        }
+        // 下划线转驼峰策略
+        if (NamingStrategy.underline_to_camel.equals(this.entity.getColumnNaming())) {
+            this.convert = !propertyName.equalsIgnoreCase(NamingStrategy.underlineToCamel(this.columnName));
+        }
+        // 原样输出策略
+        if (NamingStrategy.no_change.equals(this.entity.getColumnNaming())) {
+            this.convert = !propertyName.equalsIgnoreCase(this.columnName);
+        }
+        if (entity.isTableFieldAnnotationEnable()) {
+            this.convert = true;
+        }
+        this.propertyName = propertyName;
+        return this;
+    }
+
+    public String getPropertyType() {
+        if (null != columnType) {
+            return columnType.getType();
+        }
+        return null;
+    }
+
+    /**
+     * 按 JavaBean 规则来生成 get 和 set 方法后面的属性名称
+     * 需要处理一下特殊情况:
+     * <p>
+     * 1、如果只有一位,转换为大写形式
+     * 2、如果多于 1 位,只有在第二位是小写的情况下,才会把第一位转为小写
+     * <p>
+     * 我们并不建议在数据库对应的对象中使用基本类型,因此这里不会考虑基本类型的情况
+     */
+    public String getCapitalName() {
+        if (propertyName.length() == 1) {
+            return propertyName.toUpperCase();
+        }
+        if (Character.isLowerCase(propertyName.charAt(1))) {
+            return Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
+        }
+        return propertyName;
+    }
+
+    /**
+     * 获取注解字段名称
+     *
+     * @return 字段
+     * @since 3.3.2
+     */
+    public String getAnnotationColumnName() {
+        if (keyWords) {
+            if (columnName.startsWith("\"")) {
+                return String.format("\\\"%s\\\"", name);
+            }
+        }
+        return columnName;
+    }
+
+    /**
+     * 是否为乐观锁字段
+     *
+     * @return 是否为乐观锁字段
+     * @since 3.5.0
+     */
+    public boolean isVersionField() {
+        String propertyName = entity.getVersionPropertyName();
+        String columnName = entity.getVersionColumnName();
+        return StringUtils.isNotBlank(propertyName) && this.propertyName.equals(propertyName)
+            || StringUtils.isNotBlank(columnName) && this.name.equalsIgnoreCase(columnName);
+    }
+
+    /**
+     * 是否为逻辑删除字段
+     *
+     * @return 是否为逻辑删除字段
+     * @since 3.5.0
+     */
+    public boolean isLogicDeleteField() {
+        String propertyName = entity.getLogicDeletePropertyName();
+        String columnName = entity.getLogicDeleteColumnName();
+        return StringUtils.isNotBlank(propertyName) && this.propertyName.equals(propertyName)
+            || StringUtils.isNotBlank(columnName) && this.name.equalsIgnoreCase(columnName);
+    }
+
+    /**
+     * 设置主键
+     *
+     * @param autoIncrement 自增标识
+     * @return this
+     * @since 3.5.0
+     */
+    public TableField primaryKey(boolean autoIncrement) {
+        this.keyFlag = true;
+        this.keyIdentityFlag = autoIncrement;
+        return this;
+    }
+
+    /**
+     * @param type 类型
+     * @return this
+     */
+    public TableField setType(String type) {
+        this.type = type;
+        return this;
+    }
+
+    public TableField setComment(String comment) {
+        //TODO 暂时挪动到这
+        this.comment = this.globalConfig.isSwagger()
+            && StringUtils.isNotBlank(comment) ? comment.replace("\"", "\\\"") : comment;
+        return this;
+    }
+
+    public TableField setColumnName(String columnName) {
+        this.columnName = columnName;
+        IKeyWordsHandler keyWordsHandler = dataSourceConfig.getKeyWordsHandler();
+        if (keyWordsHandler != null && keyWordsHandler.isKeyWords(columnName)) {
+            this.keyWords = true;
+            this.columnName = keyWordsHandler.formatColumn(columnName);
+        }
+        return this;
+    }
+
+    public TableField setCustomMap(Map<String, Object> customMap) {
+        this.customMap = customMap;
+        return this;
+    }
+
+    public boolean isConvert() {
+        return convert;
+    }
+
+    public boolean isKeyFlag() {
+        return keyFlag;
+    }
+
+    public boolean isKeyIdentityFlag() {
+        return keyIdentityFlag;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public IColumnType getColumnType() {
+        return columnType;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public String getFill() {
+        if (StringUtils.isBlank(fill)) {
+            entity.getTableFillList().stream()
+                //忽略大写字段问题
+                .filter(tf -> tf instanceof Column && tf.getName().equalsIgnoreCase(name)
+                    || tf instanceof Property && tf.getName().equals(propertyName))
+                .findFirst().ifPresent(tf -> this.fill = tf.getFieldFill().name());
+        }
+        return fill;
+    }
+
+    public boolean isKeyWords() {
+        return keyWords;
+    }
+
+    public String getColumnName() {
+        return columnName;
+    }
+
+    public Map<String, Object> getCustomMap() {
+        return customMap;
+    }
+
+    public MetaInfo getMetaInfo() {
+        return metaInfo;
+    }
+
+    public void setMetaInfo(MetaInfo metaInfo) {
+        this.metaInfo = metaInfo;
+    }
+
+    /**
+     * 元数据信息
+     *
+     * @author nieqiurong 2021/2/8
+     * @since 3.5.0
+     */
+    public static class MetaInfo {
+
+        /**
+         * 表名称
+         */
+        private String tableName;
+
+        /**
+         * 字段名称
+         */
+        private String columnName;
+
+        /**
+         * 字段长度
+         */
+        private int length;
+
+        /**
+         * 是否非空
+         */
+        private boolean nullable;
+
+        /**
+         * 字段注释
+         */
+        private String remarks;
+
+        /**
+         * 字段默认值
+         */
+        private String defaultValue;
+
+        /**
+         * 字段精度
+         */
+        private int scale;
+
+        /**
+         * JDBC类型
+         */
+        private JdbcType jdbcType;
+
+        public MetaInfo(DatabaseMetaDataWrapper.Column column, TableInfo tableInfo) {
+            if (column != null) {
+                this.tableName = tableInfo.getName();
+                this.columnName = column.getName();
+                this.length = column.getLength();
+                this.nullable = column.isNullable();
+                this.remarks = column.getRemarks();
+                this.defaultValue = column.getDefaultValue();
+                this.scale = column.getScale();
+                this.jdbcType = column.getJdbcType();
+            }
+        }
+
+        public int getLength() {
+            return length;
+        }
+
+        public boolean isNullable() {
+            return nullable;
+        }
+
+        public String getRemarks() {
+            return remarks;
+        }
+
+        public String getDefaultValue() {
+            return defaultValue;
+        }
+
+        public int getScale() {
+            return scale;
+        }
+
+        public JdbcType getJdbcType() {
+            return jdbcType;
+        }
+
+        @Override
+        public String toString() {
+            return "MetaInfo{" +
+                "tableName=" + tableName +
+                ", columnName=" + columnName +
+                ", length=" + length +
+                ", nullable=" + nullable +
+                ", remarks='" + remarks + '\'' +
+                ", defaultValue='" + defaultValue + '\'' +
+                ", scale=" + scale +
+                ", jdbcType=" + jdbcType +
+                '}';
+        }
+    }
+}

+ 357 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java

@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.po;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.builder.Entity;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * 表信息,关联到当前字段信息
+ *
+ * @author YangHu, lanjerry
+ * @since 2016/8/30
+ */
+public class TableInfo {
+
+    /**
+     * 策略配置
+     */
+    private final StrategyConfig strategyConfig;
+
+    /**
+     * 全局配置信息
+     */
+    private final GlobalConfig globalConfig;
+
+    /**
+     * 包导入信息
+     */
+    private final Set<String> importPackages = new TreeSet<>();
+
+    /**
+     * 是否转换
+     */
+    private boolean convert;
+
+    /**
+     * 表名称
+     */
+    private String name;
+
+    /**
+     * 表注释
+     */
+    private String comment;
+
+    /**
+     * 实体名称
+     */
+    private String entityName;
+
+    /**
+     * mapper名称
+     */
+    private String mapperName;
+
+    /**
+     * xml名称
+     */
+    private String xmlName;
+
+    /**
+     * service名称
+     */
+    private String serviceName;
+
+    /**
+     * serviceImpl名称
+     */
+    private String serviceImplName;
+
+    /**
+     * controller名称
+     */
+    private String controllerName;
+
+    /**
+     * 表字段
+     */
+    private final List<TableField> fields = new ArrayList<>();
+
+    /**
+     * 是否有主键
+     */
+    private boolean havePrimaryKey;
+
+    /**
+     * 公共字段
+     */
+    private final List<TableField> commonFields = new ArrayList<>();
+
+    /**
+     * 字段名称集
+     */
+    private String fieldNames;
+
+    /**
+     * 实体
+     */
+    private final Entity entity;
+
+    /**
+     * 构造方法
+     *
+     * @param configBuilder 配置构建
+     * @param name          表名
+     * @since 3.5.0
+     */
+    public TableInfo(@NotNull ConfigBuilder configBuilder, @NotNull String name) {
+        this.strategyConfig = configBuilder.getStrategyConfig();
+        this.globalConfig = configBuilder.getGlobalConfig();
+        this.entity = configBuilder.getStrategyConfig().entity();
+        this.name = name;
+    }
+
+    /**
+     * @since 3.5.0
+     */
+    protected TableInfo setConvert() {
+        if (strategyConfig.startsWithTablePrefix(name) || entity.isTableFieldAnnotationEnable()) {
+            this.convert = true;
+        } else {
+            this.convert = !entityName.equalsIgnoreCase(name);
+        }
+        return this;
+    }
+
+    public String getEntityPath() {
+        return entityName.substring(0, 1).toLowerCase() + entityName.substring(1);
+    }
+
+    /**
+     * @param entityName 实体名称
+     * @return this
+     */
+    public TableInfo setEntityName(@NotNull String entityName) {
+        this.entityName = entityName;
+        //TODO 先放置在这里
+        setConvert();
+        return this;
+    }
+
+    /**
+     * 添加字段
+     *
+     * @param field 字段
+     * @since 3.5.0
+     */
+    public void addField(@NotNull TableField field) {
+        if (entity.matchIgnoreColumns(field.getColumnName())) {
+            // 忽略字段不在处理
+            return;
+        } else if (entity.matchSuperEntityColumns(field.getColumnName())) {
+            this.commonFields.add(field);
+        } else {
+            this.fields.add(field);
+        }
+    }
+
+    /**
+     * @param pkgs 包空间
+     * @return this
+     * @since 3.5.0
+     */
+    public TableInfo addImportPackages(@NotNull String... pkgs) {
+        return addImportPackages(Arrays.asList(pkgs));
+    }
+
+    public TableInfo addImportPackages(@NotNull List<String> pkgList) {
+        importPackages.addAll(pkgList);
+        return this;
+    }
+
+    /**
+     * 转换filed实体为 xml mapper 中的 base column 字符串信息
+     */
+    public String getFieldNames() {
+        //TODO 感觉这个也啥必要,不打算公开set方法了
+        if (StringUtils.isBlank(fieldNames)) {
+            this.fieldNames = this.fields.stream().map(TableField::getColumnName).collect(Collectors.joining(", "));
+        }
+        return this.fieldNames;
+    }
+
+    /**
+     * 导包处理
+     *
+     * @since 3.5.0
+     */
+    public void importPackage() {
+        String superEntity = entity.getSuperClass();
+        if (StringUtils.isNotBlank(superEntity)) {
+            // 自定义父类
+            this.importPackages.add(superEntity);
+        } else {
+            if (entity.isActiveRecord()) {
+                // 无父类开启 AR 模式
+                this.importPackages.add(Model.class.getCanonicalName());
+            }
+        }
+        if (entity.isSerialVersionUID() || entity.isActiveRecord()) {
+            this.importPackages.add(Serializable.class.getCanonicalName());
+        }
+        if (this.isConvert()) {
+            this.importPackages.add(TableName.class.getCanonicalName());
+        }
+        IdType idType = entity.getIdType();
+        if (null != idType && this.isHavePrimaryKey()) {
+            // 指定需要 IdType 场景
+            this.importPackages.add(IdType.class.getCanonicalName());
+            this.importPackages.add(TableId.class.getCanonicalName());
+        }
+        this.fields.forEach(field -> {
+            IColumnType columnType = field.getColumnType();
+            if (null != columnType && null != columnType.getPkg()) {
+                importPackages.add(columnType.getPkg());
+            }
+            if (field.isKeyFlag()) {
+                // 主键
+                if (field.isConvert() || field.isKeyIdentityFlag()) {
+                    importPackages.add(TableId.class.getCanonicalName());
+                }
+                // 自增
+                if (field.isKeyIdentityFlag()) {
+                    importPackages.add(IdType.class.getCanonicalName());
+                }
+            } else if (field.isConvert()) {
+                // 普通字段
+                importPackages.add(com.baomidou.mybatisplus.annotation.TableField.class.getCanonicalName());
+            }
+            if (null != field.getFill()) {
+                // 填充字段
+                importPackages.add(com.baomidou.mybatisplus.annotation.TableField.class.getCanonicalName());
+                //TODO 好像default的不用处理也行,这个做优化项目.
+                importPackages.add(FieldFill.class.getCanonicalName());
+            }
+            if (field.isVersionField()) {
+                this.importPackages.add(Version.class.getCanonicalName());
+            }
+            if (field.isLogicDeleteField()) {
+                this.importPackages.add(TableLogic.class.getCanonicalName());
+            }
+        });
+    }
+
+    /**
+     * 处理表信息(文件名与导包)
+     *
+     * @since 3.5.0
+     */
+    public void processTable() {
+        String entityName = entity.getNameConvert().entityNameConvert(this);
+        this.setEntityName(entity.getConverterFileName().convert(entityName));
+        this.mapperName = strategyConfig.mapper().getConverterMapperFileName().convert(entityName);
+        this.xmlName = strategyConfig.mapper().getConverterXmlFileName().convert(entityName);
+        this.serviceName = strategyConfig.service().getConverterServiceFileName().convert(entityName);
+        this.serviceImplName = strategyConfig.service().getConverterServiceImplFileName().convert(entityName);
+        this.controllerName = strategyConfig.controller().getConverterFileName().convert(entityName);
+        this.importPackage();
+    }
+
+    public TableInfo setComment(String comment) {
+        //TODO 暂时挪动到这
+        this.comment = this.globalConfig.isSwagger()
+            && StringUtils.isNotBlank(comment) ? comment.replace("\"", "\\\"") : comment;
+        return this;
+    }
+
+    public TableInfo setHavePrimaryKey(boolean havePrimaryKey) {
+        this.havePrimaryKey = havePrimaryKey;
+        return this;
+    }
+
+    @NotNull
+    public Set<String> getImportPackages() {
+        return importPackages;
+    }
+
+    public boolean isConvert() {
+        return convert;
+    }
+
+    public TableInfo setConvert(boolean convert) {
+        this.convert = convert;
+        return this;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public String getEntityName() {
+        return entityName;
+    }
+
+    public String getMapperName() {
+        return mapperName;
+    }
+
+    public String getXmlName() {
+        return xmlName;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public String getServiceImplName() {
+        return serviceImplName;
+    }
+
+    public String getControllerName() {
+        return controllerName;
+    }
+
+    @NotNull
+    public List<TableField> getFields() {
+        return fields;
+    }
+
+    public boolean isHavePrimaryKey() {
+        return havePrimaryKey;
+    }
+
+    @NotNull
+    public List<TableField> getCommonFields() {
+        return commonFields;
+    }
+}

+ 19 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/package-info.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 代码生成器,输出相关类
+ */
+package com.baomidou.mybatisplus.generator.config.po;

+ 42 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/AbstractDbQuery.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import com.baomidou.mybatisplus.generator.config.IDbQuery;
+
+/**
+ * 表数据查询抽象类
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public abstract class AbstractDbQuery implements IDbQuery {
+
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return false;
+    }
+
+
+    @Override
+    public String[] fieldCustom() {
+        return null;
+    }
+}

+ 77 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/ClickHouseQuery.java

@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * ClickHouse 表数据查询
+ *
+ * @author gaosheng
+ * @since 2021-03-10
+ */
+public class ClickHouseQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM system.tables WHERE 1=1 ";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "select * from system.columns where table='%s'";
+    }
+
+    @Override
+    public String tableName() {
+        return "name";
+    }
+
+    @Override
+    public String tableComment() {
+        return "name";
+    }
+
+    @Override
+    public String fieldName() {
+        return "name";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "type";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "comment";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "is_in_primary_key";
+    }
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return "1".equals(results.getString("is_in_primary_key"));
+    }
+
+}

+ 73 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DB2Query.java

@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * DB2 表数据查询
+ *
+ * @author zhanyao
+ * @since 2018-05-16
+ */
+public class DB2Query extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM SYSCAT.TABLES where tabschema='%s'";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT * FROM syscat.columns WHERE tabschema='%s' AND tabname='%s'";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "TABNAME";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "REMARKS";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "COLNAME";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "TYPENAME";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "REMARKS";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "IDENTITY";
+    }
+
+}

+ 79 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DMQuery.java

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * DM 表数据查询
+ *
+ * @author halower,daiby
+ * @since 2019-06-27
+ */
+public class DMQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM (SELECT DISTINCT T1.TABLE_NAME AS TABLE_NAME,T2.COMMENTS AS TABLE_COMMENT FROM USER_TAB_COLUMNS T1 " +
+            "INNER JOIN USER_TAB_COMMENTS T2 ON T1.TABLE_NAME = T2.TABLE_NAME) WHERE 1=1 ";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return
+                "SELECT T2.COLUMN_NAME,T1.COMMENTS," +
+                        "CASE WHEN T2.DATA_TYPE='NUMBER' THEN (CASE WHEN T2.DATA_PRECISION IS NULL THEN T2.DATA_TYPE WHEN NVL(T2.DATA_SCALE, 0) > 0 THEN T2.DATA_TYPE||'('||T2.DATA_PRECISION||','||T2.DATA_SCALE||')' ELSE T2.DATA_TYPE||'('||T2.DATA_PRECISION||')' END) ELSE T2.DATA_TYPE END DATA_TYPE ," +
+                        "CASE WHEN CONSTRAINT_TYPE='P' THEN 'PRI' END AS KEY " +
+                        "FROM USER_COL_COMMENTS T1, USER_TAB_COLUMNS T2, " +
+                        "(SELECT T4.TABLE_NAME, T4.COLUMN_NAME ,T5.CONSTRAINT_TYPE " +
+                        "FROM USER_CONS_COLUMNS T4, USER_CONSTRAINTS T5 " +
+                        "WHERE T4.CONSTRAINT_NAME = T5.CONSTRAINT_NAME " +
+                        "AND T5.CONSTRAINT_TYPE = 'P')T3 " +
+                        "WHERE T1.TABLE_NAME = T2.TABLE_NAME AND " +
+                        "T1.COLUMN_NAME=T2.COLUMN_NAME AND " +
+                        "T1.TABLE_NAME = T3.TABLE_NAME(+) AND " +
+                        "T1.COLUMN_NAME=T3.COLUMN_NAME(+)   AND " +
+                        "T1.TABLE_NAME = '%s' " +
+                        "ORDER BY T2.TABLE_NAME,T2.COLUMN_ID";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+    @Override
+    public String tableComment() {
+        return "TABLE_COMMENT";
+    }
+
+    @Override
+    public String fieldName() {
+        return "COLUMN_NAME";
+    }
+
+    @Override
+    public String fieldType() {
+        return "DATA_TYPE";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "COMMENTS";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+}

+ 290 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DbQueryDecorator.java

@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.IDbQuery;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.po.LikeTable;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * DbQuery 装饰器
+ *
+ * @author nieqiurong 2020/9/17.
+ * @author hubin
+ * @since 3.5.0
+ */
+public class DbQueryDecorator extends AbstractDbQuery {
+    private final IDbQuery dbQuery;
+    private final Connection connection;
+    private final DbType dbType;
+    private final StrategyConfig strategyConfig;
+    private final String schema;
+    private final Logger logger;
+
+    public DbQueryDecorator(@NotNull DataSourceConfig dataSourceConfig, @NotNull StrategyConfig strategyConfig) {
+        this.dbQuery = dataSourceConfig.getDbQuery();
+        this.connection = dataSourceConfig.getConn();
+        this.dbType = dataSourceConfig.getDbType();
+        this.strategyConfig = strategyConfig;
+        this.schema = dataSourceConfig.getSchemaName();
+        this.logger = LoggerFactory.getLogger(dbQuery.getClass());
+    }
+
+    @Override
+    public String tablesSql() {
+        String tablesSql = dbQuery.tablesSql();
+        if (DbType.POSTGRE_SQL == dbType || DbType.KINGBASE_ES == dbType || DbType.DB2 == dbType || DbType.ORACLE == dbType) {
+            tablesSql = String.format(tablesSql, this.schema);
+        }
+        if (strategyConfig.isEnableSqlFilter()) {
+            StringBuilder sql = new StringBuilder(tablesSql);
+            LikeTable table;
+            Set<String> tables;
+            if ((table = strategyConfig.getLikeTable()) != null) {
+                sql.append(" AND ").append(dbQuery.tableName()).append(" LIKE '").append(table.getValue()).append("'");
+            } else if ((table = strategyConfig.getNotLikeTable()) != null) {
+                sql.append(" AND ").append(dbQuery.tableName()).append(" NOT LIKE '").append(table.getValue()).append("'");
+            }
+            if (!(tables = strategyConfig.getInclude()).isEmpty()) {
+                sql.append(" AND ").append(dbQuery.tableName()).append(" IN (")
+                    .append(tables.stream().map(tb -> "'" + tb + "'").collect(Collectors.joining(","))).append(")");
+            } else if (!(tables = strategyConfig.getExclude()).isEmpty()) {
+                sql.append(" AND ").append(dbQuery.tableName()).append(" NOT IN (")
+                    .append(tables.stream().map(tb -> "'" + tb + "'").collect(Collectors.joining(","))).append(")");
+            }
+            return sql.toString();
+        }
+        return tablesSql;
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return dbQuery.tableFieldsSql();
+    }
+
+    /**
+     * 扩展{@link #tableFieldsSql()}方法
+     *
+     * @param tableName 表名
+     * @return 查询表字段语句
+     */
+    public String tableFieldsSql(String tableName) {
+        String tableFieldsSql = this.tableFieldsSql();
+        if (DbType.KINGBASE_ES == dbType || DbType.DB2 == dbType) {
+            tableFieldsSql = String.format(tableFieldsSql, this.schema, tableName);
+        } else if (DbType.ORACLE == dbType) {
+            tableFieldsSql = String.format(tableFieldsSql.replace("#schema", this.schema), tableName, tableName.toUpperCase());
+        } else if (DbType.DM == dbType) {
+            tableName = tableName.toUpperCase();
+            tableFieldsSql = String.format(tableFieldsSql, tableName);
+        } else if (DbType.POSTGRE_SQL == dbType) {
+            tableFieldsSql = String.format(tableFieldsSql, tableName, tableName, tableName);
+        } else {
+            tableFieldsSql = String.format(tableFieldsSql, tableName);
+        }
+        return tableFieldsSql;
+    }
+
+    @Override
+    public String tableName() {
+        return dbQuery.tableName();
+    }
+
+    @Override
+    public String tableComment() {
+        return dbQuery.tableComment();
+    }
+
+    @Override
+    public String fieldName() {
+        return dbQuery.fieldName();
+    }
+
+    @Override
+    public String fieldType() {
+        return dbQuery.fieldType();
+    }
+
+    @Override
+    public String fieldComment() {
+        return dbQuery.fieldComment();
+    }
+
+    @Override
+    public String fieldKey() {
+        return dbQuery.fieldKey();
+    }
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) {
+        try {
+            return dbQuery.isKeyIdentity(results);
+        } catch (SQLException e) {
+            logger.warn("判断主键自增错误:{}", e.getMessage());
+            // ignore 这个看到在查H2的时候出了异常,先忽略这个异常了.
+        }
+        return false;
+    }
+
+    @Override
+    public String[] fieldCustom() {
+        return dbQuery.fieldCustom();
+    }
+
+    public Map<String, Object> getCustomFields(ResultSet resultSet) {
+        String[] fcs = this.fieldCustom();
+        if (null != fcs) {
+            Map<String, Object> customMap = CollectionUtils.newHashMapWithExpectedSize(fcs.length);
+            for (String fc : fcs) {
+                try {
+                    customMap.put(fc, resultSet.getObject(fc));
+                } catch (SQLException sqlException) {
+                    throw new RuntimeException("获取自定义字段错误:", sqlException);
+                }
+            }
+            return customMap;
+        }
+        return Collections.emptyMap();
+    }
+
+    /**
+     * 执行 SQL 查询,回调返回结果
+     *
+     * @param sql      执行SQL
+     * @param consumer 结果处理
+     * @throws SQLException
+     */
+    public void execute(String sql, Consumer<ResultSetWrapper> consumer) throws SQLException {
+        logger.debug("执行SQL:{}", sql);
+        int count = 0;
+        long start = System.nanoTime();
+        try (PreparedStatement preparedStatement = connection.prepareStatement(sql);
+             ResultSet resultSet = preparedStatement.executeQuery()) {
+            while (resultSet.next()) {
+                consumer.accept(new ResultSetWrapper(resultSet, this, this.dbType));
+                count++;
+            }
+            long end = System.nanoTime();
+            logger.debug("返回记录数:{},耗时(ms):{}", count, (end - start) / 1000000);
+        }
+    }
+
+    public Connection getConnection() {
+        return connection;
+    }
+
+    public void closeConnection() {
+        Optional.ofNullable(connection).ifPresent((con) -> {
+            try {
+                con.close();
+            } catch (SQLException sqlException) {
+                sqlException.printStackTrace();
+            }
+        });
+    }
+
+    public static class ResultSetWrapper {
+
+        private final IDbQuery dbQuery;
+
+        private final ResultSet resultSet;
+
+        private final DbType dbType;
+
+        ResultSetWrapper(ResultSet resultSet, IDbQuery dbQuery, DbType dbType) {
+            this.resultSet = resultSet;
+            this.dbQuery = dbQuery;
+            this.dbType = dbType;
+        }
+
+        public ResultSet getResultSet() {
+            return resultSet;
+        }
+
+        public String getStringResult(String columnLabel) {
+            try {
+                return resultSet.getString(columnLabel);
+            } catch (SQLException sqlException) {
+                throw new RuntimeException(String.format("读取[%s]字段出错!", columnLabel), sqlException);
+            }
+        }
+
+        /**
+         * @return 获取字段注释
+         */
+        public String getFiledComment() {
+            return getComment(dbQuery.fieldComment());
+        }
+
+        /**
+         * 获取格式化注释
+         *
+         * @param columnLabel 字段列
+         * @return 注释
+         */
+        private String getComment(String columnLabel) {
+            return StringUtils.isNotBlank(columnLabel) ? formatComment(getStringResult(columnLabel)) : StringPool.EMPTY;
+        }
+
+        /**
+         * 获取表注释
+         *
+         * @return 表注释
+         */
+        public String getTableComment() {
+            return getComment(dbQuery.tableComment());
+        }
+
+        /**
+         * @param comment 注释
+         * @return 格式化内容
+         */
+        public String formatComment(String comment) {
+            return StringUtils.isBlank(comment) ? StringPool.EMPTY : comment.replaceAll("\r\n", "\t");
+        }
+
+        /**
+         * @return 是否主键
+         */
+        public boolean isPrimaryKey() {
+            String key = this.getStringResult(dbQuery.fieldKey());
+            if (DbType.DB2 == dbType || DbType.SQLITE == dbType || DbType.CLICK_HOUSE == dbType) {
+                return StringUtils.isNotBlank(key) && "1".equals(key);
+            } else {
+                return StringUtils.isNotBlank(key) && "PRI".equalsIgnoreCase(key);
+            }
+        }
+    }
+}

+ 56 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DbQueryRegistry.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.generator.config.IDbQuery;
+
+/**
+ * @author nieqiuqiu
+ * @date 2020-01-09
+ * @since 3.3.1
+ */
+public class DbQueryRegistry {
+
+    private final Map<DbType, IDbQuery> db_query_enum_map = new EnumMap<>(DbType.class);
+
+    public DbQueryRegistry() {
+        db_query_enum_map.put(DbType.ORACLE, new OracleQuery());
+        db_query_enum_map.put(DbType.SQL_SERVER, new SqlServerQuery());
+        db_query_enum_map.put(DbType.POSTGRE_SQL, new PostgreSqlQuery());
+        db_query_enum_map.put(DbType.DB2, new DB2Query());
+        db_query_enum_map.put(DbType.MARIADB, new MariadbQuery());
+        db_query_enum_map.put(DbType.H2, new H2Query());
+        db_query_enum_map.put(DbType.SQLITE, new SqliteQuery());
+        db_query_enum_map.put(DbType.DM, new DMQuery());
+        db_query_enum_map.put(DbType.KINGBASE_ES, new KingbaseESQuery());
+        db_query_enum_map.put(DbType.MYSQL, new MySqlQuery());
+        db_query_enum_map.put(DbType.GAUSS, new GaussQuery());
+        db_query_enum_map.put(DbType.OSCAR, new OscarQuery());
+        db_query_enum_map.put(DbType.FIREBIRD, new FirebirdQuery());
+        db_query_enum_map.put(DbType.XU_GU, new XuguQuery());
+        db_query_enum_map.put(DbType.CLICK_HOUSE, new ClickHouseQuery());
+        db_query_enum_map.put(DbType.GBASE, new GbaseQuery());
+        db_query_enum_map.put(DbType.SYBASE, new SybaseQuery());
+    }
+
+    public IDbQuery getDbQuery(DbType dbType) {
+        return db_query_enum_map.get(dbType);
+    }
+}

+ 95 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/FirebirdQuery.java

@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * MySql 表数据查询
+ *
+ * @author steven ma
+ * @since 2020-08-20
+ */
+public class FirebirdQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "select trim(rdb$relation_name) as rdb$relation_name " +
+            "from rdb$relations " +
+            "where rdb$view_blr is null " +
+            "and (rdb$system_flag is null or rdb$system_flag = 0)";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "select trim(f.rdb$relation_name) AS rdb$relation_name, " +
+            "trim(f.rdb$field_name) AS FIELD, t.rdb$type_name AS  TYPE, " +
+            "(CASE WHEN ( " +
+            "   SELECT count(*) " +
+            "   FROM RDB$RELATION_CONSTRAINTS RC " +
+            "   LEFT JOIN RDB$INDICES I ON (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) " +
+            "   LEFT JOIN RDB$INDEX_SEGMENTS S ON (S.RDB$INDEX_NAME = I.RDB$INDEX_NAME) " +
+            "   WHERE (RC.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY') " +
+            "   AND (I.RDB$RELATION_NAME = f.rdb$relation_name  ) " +
+            "   AND (S.RDB$FIELD_NAME = f.rdb$field_name) " +
+            ") > 0 THEN 'PRI' ELSE '' END) AS pk " +
+            "from rdb$relation_fields f " +
+            "join rdb$relations r on f.rdb$relation_name = r.rdb$relation_name " +
+            "JOIN rdb$fields fs ON f.rdb$field_source = fs.rdb$field_name " +
+            "JOIN rdb$types  t ON fs.rdb$field_type = t.rdb$type " +
+            "and r.rdb$view_blr is NULL " +
+            "AND t.rdb$field_name = 'RDB$FIELD_TYPE' " +
+            "and (r.rdb$system_flag is null or r.rdb$system_flag = 0) " +
+            "AND f.rdb$relation_name = '%s' " +
+            "order by 1, f.rdb$field_position";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "rdb$relation_name";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "FIELD";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "TYPE";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "PK";
+    }
+
+}

+ 77 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/GaussQuery.java

@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * Gauss 表数据查询
+ *
+ * @author halower
+ * @since 2019-06-27
+ */
+public class GaussQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM (SELECT DISTINCT T1.TABLE_NAME,T2.COMMENTS AS TABLE_COMMENT FROM USER_TAB_COLUMNS T1 " +
+            "LEFT JOIN USER_TAB_COMMENTS T2 ON T1.TABLE_NAME = T2.TABLE_NAME ) a WHERE 1=1 ";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return
+            "SELECT T1.COLUMN_NAME,T2.COMMENTS,T1.DATA_TYPE," +
+                "CASE WHEN CONSTRAINT_TYPE='P' THEN 'PRI' END AS KEY " +
+                "FROM USER_TAB_COLUMNS T1 " +
+                "LEFT JOIN USER_COL_COMMENTS T2 ON " +
+                "(T1.TABLE_NAME = T2.TABLE_NAME AND T1.COLUMN_NAME = T2.COLUMN_NAME) " +
+                "LEFT JOIN (" +
+                "SELECT T4.TABLE_NAME,T4.COLUMN_NAME,T5.CONSTRAINT_TYPE FROM USER_CONS_COLUMNS T4,USER_CONSTRAINTS T5 " +
+                "WHERE T4.CONSTRAINT_NAME = T5.CONSTRAINT_NAME AND T5.CONSTRAINT_TYPE = 'P'" +
+                ")T3 ON (T1.TABLE_NAME = T3.TABLE_NAME AND T1.COLUMN_NAME = T3.COLUMN_NAME) " +
+                "WHERE T1.TABLE_NAME = '%s' " +
+                "ORDER BY T1.TABLE_NAME,T1.COLUMN_ID";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+    @Override
+    public String tableComment() {
+        return "TABLE_COMMENT";
+    }
+
+    @Override
+    public String fieldName() {
+        return "COLUMN_NAME";
+    }
+
+    @Override
+    public String fieldType() {
+        return "DATA_TYPE";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "COMMENTS";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+}

+ 110 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/GbaseQuery.java

@@ -0,0 +1,110 @@
+package com.baomidou.mybatisplus.generator.config.querys;
+
+
+/**
+ * https://github.com/baomidou/generator/pull/83
+ *
+ * @author lix
+ */
+public class GbaseQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "select * from systables where 1=1";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "select a.tabname,b.colname,b.coltype, " +
+            "case b.colname " +
+            "when 'id' then 'PRI' " +
+            "end as key, " +
+            "case b.coltype " +
+            "when '0' then 'CHAR' " +
+            "when '1' then 'SMALLINT' " +
+            "when '2' then 'INTEGER' " +
+            "when '3' then 'FLOAT' " +
+            "when '4' then 'SMALLFLOAT' " +
+            "when '5' then 'DECIMAL' " +
+            "when '6' then 'SERIAL' " +
+            "when '7' then 'DATE' " +
+            "when '8' then 'MONEY' " +
+            "when '9' then 'NULL' " +
+            "when '10' then 'DATETIME' " +
+            "when '11' then 'BYTE' " +
+            "when '12' then 'TEXT' " +
+            "when '13' then 'VARCHAR' " +
+            "when '14' then 'INTERVAL' " +
+            "when '15' then 'NCHAR' " +
+            "when '16' then 'NVARCHAR' " +
+            "when '17' then 'INT8' " +
+            "when '18' then 'SERIAL8' " +
+            "when '19' then 'SET' " +
+            "when '20' then 'MULTISET' " +
+            "when '21' then 'LIST' " +
+            "when '22' then 'Unnamed ROW' " +
+            "when '40' then 'LVARCHAR' " +
+            "when '41' then 'CLOB' " +
+            "when '43' then 'BLOB' " +
+            "when '44' then 'BOOLEAN' " +
+            "when '256' then 'CHAR' " +
+            "when '257' then 'SMALLINT' " +
+            "when '258' then 'INTEGER' " +
+            "when '259' then 'FLOAT' " +
+            "when '260' then 'REAL' " +
+            "when '261' then 'DECIMAL' " +
+            "when '262' then 'SERIAL' " +
+            "when '263' then 'DATE' " +
+            "when '264' then 'MONEY' " +
+            "when '266' then 'DATETIME' " +
+            "when '267' then 'BYTE' " +
+            "when '268' then 'TEXT' " +
+            "when '269' then 'VARCHAR' " +
+            "when '270' then 'INTERVAL' " +
+            "when '271' then 'NCHAR' " +
+            "when '272' then 'NVARCHAR' " +
+            "when '273' then 'INT8' " +
+            "when '274' then 'SERIAL8' " +
+            "when '275' then 'SET' " +
+            "when '276' then 'MULTISET' " +
+            "when '277' then 'LIST' " +
+            "when '278' then 'Unnamed ROW' " +
+            "when '296' then 'LVARCHAR' " +
+            "when '297' then 'CLOB' " +
+            "when '298' then 'BLOB' " +
+            "when '299' then 'BOOLEAN' " +
+            "when '4118' then 'Named ROW' " +
+            "end as coltypename, b.colno from systables a left join syscolumns b on a.tabid=b.tabid where a.tabid>99 and a.tabtype='T' and a.tabname = 'lap20' order by a.tabname,b.colno;";
+    }
+
+    @Override
+    public String tableName() {
+        return "tabname";
+    }
+
+    @Override
+    public String tableComment() {
+        return "tabname";
+    }
+
+    @Override
+    public String fieldName() {
+        return "colname";
+    }
+
+    @Override
+    public String fieldType() {
+        return "coltypename";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "colname";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "key";
+    }
+
+}

+ 75 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/H2Query.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * H2Database 表数据查询
+ *
+ * @author yuxiaobin
+ * @since 2019-01-8
+ */
+public class H2Query extends AbstractDbQuery {
+
+    public static final String PK_QUERY_SQL = "select * from INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = '%s'";
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE 1=1 ";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= '%s' ";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+    @Override
+    public String tableComment() {
+        return "REMARKS";
+    }
+
+    @Override
+    public String fieldName() {
+        return "COLUMN_NAME";
+    }
+
+    @Override
+    public String fieldType() {
+        return "TYPE_NAME";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "REMARKS";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "PRIMARY_KEY";
+    }
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return results.getString("SEQUENCE_NAME") != null;
+    }
+}

+ 75 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/KingbaseESQuery.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * KingbaseES 表数据查询
+ *
+ * @author kingbase
+ * @since 2019-10-12
+ */
+public class KingbaseESQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT A.tablename, obj_description(relfilenode, 'sys_class') AS comments FROM sys_tables A, sys_class B WHERE A.schemaname='%s' AND A.tablename = B.relname";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT A.attname AS name, format_type(A.atttypid, A.atttypmod) AS type,col_description(A.attrelid, A.attnum) AS comment, (CASE C.contype WHEN 'p' THEN 'PRI' ELSE '' END) AS key " +
+            "FROM sys_attribute A LEFT JOIN sys_constraint C ON A.attnum = C.conkey[1] AND A.attrelid = C.conrelid " +
+            "WHERE  A.attrelid = '%s.%s'::regclass AND A.attnum > 0 AND NOT A.attisdropped ORDER  BY A.attnum";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "tablename";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "comments";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "name";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "type";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "comment";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "key";
+    }
+
+}

+ 81 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/MariadbQuery.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * MySql 表数据查询
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public class MariadbQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "show table status WHERE 1=1 ";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "show full columns from `%s`";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "NAME";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "COMMENT";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "FIELD";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "TYPE";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "COMMENT";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return "auto_increment".equals(results.getString("Extra"));
+    }
+}

+ 81 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/MySqlQuery.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * MySql 表数据查询
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public class MySqlQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "show table status WHERE 1=1 ";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "show full columns from `%s`";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "NAME";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "COMMENT";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "FIELD";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "TYPE";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "COMMENT";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return "auto_increment".equals(results.getString("Extra"));
+    }
+}

+ 82 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/OracleQuery.java

@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * Oracle 表数据查询
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public class OracleQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM ALL_TAB_COMMENTS WHERE OWNER='%s'";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT A.COLUMN_NAME, CASE WHEN A.DATA_TYPE='NUMBER' THEN "
+            + "(CASE WHEN A.DATA_PRECISION IS NULL THEN A.DATA_TYPE "
+            + "WHEN NVL(A.DATA_SCALE, 0) > 0 THEN A.DATA_TYPE||'('||A.DATA_PRECISION||','||A.DATA_SCALE||')' "
+            + "ELSE A.DATA_TYPE||'('||A.DATA_PRECISION||')' END) "
+            + "ELSE A.DATA_TYPE END DATA_TYPE, B.COMMENTS,DECODE(C.POSITION, '1', 'PRI') KEY "
+            + "FROM ALL_TAB_COLUMNS A "
+            + " INNER JOIN ALL_COL_COMMENTS B ON A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME AND B.OWNER = '#schema'"
+            + " LEFT JOIN ALL_CONSTRAINTS D ON D.TABLE_NAME = A.TABLE_NAME AND D.CONSTRAINT_TYPE = 'P' AND D.OWNER = '#schema'"
+            + " LEFT JOIN ALL_CONS_COLUMNS C ON C.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.COLUMN_NAME=A.COLUMN_NAME AND C.OWNER = '#schema'"
+            + "WHERE A.OWNER = '#schema' AND (A.TABLE_NAME = '%s' OR A.TABLE_NAME = '%s') ORDER BY A.COLUMN_ID ";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "COMMENTS";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "COLUMN_NAME";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "DATA_TYPE";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "COMMENTS";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+
+}

+ 66 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/OscarQuery.java

@@ -0,0 +1,66 @@
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * <p>Oscar(神通数据库) 表数据查询</p>
+ *
+ * @author whli
+ * @version 1.0.0
+ * @since 2020/7/28 18:54
+ */
+public class OscarQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM (SELECT " +
+            "a.TABLE_NAME, " +
+            "b.COMMENTS " +
+            "FROM USER_TABLES a " +
+            "INNER JOIN USER_TAB_COMMENTS b ON (b.TABLE_TYPE = 'TABLE' AND a.TABLE_NAME = b.TABLE_NAME)) a WHERE 1=1 ";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT " +
+            "T1.COLUMN_NAME, " +
+            "T1.DATA_TYPE, " +
+            "T2.COMMENTS, " +
+            "CASE WHEN T3.CONSTRAINT_TYPE = 'P' THEN 'PRI' " +
+            "ELSE '' END KEY " +
+            "FROM USER_TAB_COLUMNS T1 " +
+            "INNER JOIN USER_COL_COMMENTS T2 ON (T1.COLUMN_NAME = T2.COLUMN_NAME) " +
+            "LEFT JOIN(SELECT a.TABLE_NAME,b.COLUMN_NAME,a.CONSTRAINT_TYPE FROM USER_CONSTRAINTS a, USER_IND_COLUMNS b " +
+            "WHERE a.CONSTRAINT_TYPE = 'P' AND a.INDEX_NAME = b.INDEX_NAME) T3 ON (T1.TABLE_NAME = T3.TABLE_NAME AND T1.COLUMN_NAME = T3.COLUMN_NAME) " +
+            "WHERE T1.TABLE_NAME = '%s' " +
+            "GROUP BY T1.COLUMN_NAME,T1.DATA_TYPE,T2.COMMENTS,T3.CONSTRAINT_TYPE ";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+    @Override
+    public String tableComment() {
+        return "COMMENTS";
+    }
+
+    @Override
+    public String fieldName() {
+        return "COLUMN_NAME";
+    }
+
+    @Override
+    public String fieldType() {
+        return "DATA_TYPE";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "COMMENTS";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+}

+ 97 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/PostgreSqlQuery.java

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * PostgreSql 表数据查询
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public class PostgreSqlQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT A.tablename, obj_description(relfilenode, 'pg_class') AS comments FROM pg_tables A, pg_class B WHERE A.schemaname='%s' AND A.tablename = B.relname";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT\n" +
+            "   A.attname AS name,format_type (A.atttypid,A.atttypmod) AS type,col_description (A.attrelid,A.attnum) AS comment,\n" +
+            "\t D.column_default,\n" +
+            "   CASE WHEN length(B.attname) > 0 THEN 'PRI' ELSE '' END AS key\n" +
+            "FROM\n" +
+            "   pg_attribute A\n" +
+            "LEFT JOIN (\n" +
+            "    SELECT\n" +
+            "        pg_attribute.attname\n" +
+            "    FROM\n" +
+            "        pg_index,\n" +
+            "        pg_class,\n" +
+            "        pg_attribute\n" +
+            "    WHERE\n" +
+            "        pg_class.oid ='\"%s\"' :: regclass\n" +
+            "    AND pg_index.indrelid = pg_class.oid\n" +
+            "    AND pg_attribute.attrelid = pg_class.oid\n" +
+            "    AND pg_attribute.attnum = ANY (pg_index.indkey)\n" +
+            ") B ON A.attname = b.attname\n" +
+            "INNER JOIN pg_class C on A.attrelid = C.oid\n" +
+            "INNER JOIN information_schema.columns D on A.attname = D.column_name\n" +
+            "WHERE A.attrelid ='\"%s\"' :: regclass AND A.attnum> 0 AND NOT A.attisdropped AND D.table_name = '%s'\n" +
+            "ORDER BY A.attnum;";
+    }
+
+    @Override
+    public String tableName() {
+        return "tablename";
+    }
+
+    @Override
+    public String tableComment() {
+        return "comments";
+    }
+
+    @Override
+    public String fieldName() {
+        return "name";
+    }
+
+    @Override
+    public String fieldType() {
+        return "type";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "comment";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "key";
+    }
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return StringUtils.isNotBlank(results.getString("column_default")) && results.getString("column_default").contains("nextval");
+    }
+}

+ 97 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SqlServerQuery.java

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * SqlServer 表数据查询
+ *
+ * @author hubin
+ * @since 2018-01-16
+ */
+public class SqlServerQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "select * from (select cast(so.name as varchar(500)) as TABLE_NAME, " +
+            "cast(sep.value as varchar(500)) as COMMENTS from sysobjects so " +
+            "left JOIN sys.extended_properties sep on sep.major_id=so.id and sep.minor_id=0 " +
+            "where (xtype='U' or xtype='v')) a where 1=1 ";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT  cast(a.name AS VARCHAR(500)) AS TABLE_NAME,cast(b.name AS VARCHAR(500)) AS COLUMN_NAME, "
+            + "cast(c.VALUE AS NVARCHAR(500)) AS COMMENTS,cast(sys.types.name AS VARCHAR (500)) AS DATA_TYPE,"
+            + "(" + " SELECT CASE count(1) WHEN 1 then 'PRI' ELSE '' END"
+            + " FROM syscolumns,sysobjects,sysindexes,sysindexkeys,systypes "
+            + " WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id (a.name) AND sysobjects.xtype = 'PK'"
+            + " AND sysobjects.parent_obj = syscolumns.id " + " AND sysindexes.id = syscolumns.id "
+            + " AND sysobjects.name = sysindexes.name AND sysindexkeys.id = syscolumns.id "
+            + " AND sysindexkeys.indid = sysindexes.indid "
+            + " AND syscolumns.colid = sysindexkeys.colid AND syscolumns.name = b.name) as 'KEY',"
+            + "  b.is_identity isIdentity "
+            + " FROM ( select name,object_id from sys.tables UNION all select name,object_id from sys.views ) a "
+            + " INNER JOIN sys.columns b ON b.object_id = a.object_id "
+            + " LEFT JOIN sys.types ON b.user_type_id = sys.types.user_type_id   "
+            + " LEFT JOIN sys.extended_properties c ON c.major_id = b.object_id AND c.minor_id = b.column_id "
+            + " WHERE a.name = '%s' and sys.types.name !='sysname' ";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "COMMENTS";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "COLUMN_NAME";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "DATA_TYPE";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "COMMENTS";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        return 1 == results.getInt("isIdentity");
+    }
+}

+ 72 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SqliteQuery.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * Sqlite 表数据查询
+ *
+ * @author chen
+ * @since 2019-05-08
+ */
+public class SqliteQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "select * from sqlite_master where type='table'";
+    }
+
+
+    @Override
+    public String tableFieldsSql() {
+        return "pragma table_info('%s');";
+    }
+
+
+    @Override
+    public String tableName() {
+        return "name";
+    }
+
+
+    @Override
+    public String tableComment() {
+        return "";
+    }
+
+
+    @Override
+    public String fieldName() {
+        return "name";
+    }
+
+
+    @Override
+    public String fieldType() {
+        return "type";
+    }
+
+
+    @Override
+    public String fieldComment() {
+        return "";
+    }
+
+
+    @Override
+    public String fieldKey() {
+        return "pk";
+    }
+}

+ 67 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SybaseQuery.java

@@ -0,0 +1,67 @@
+package com.baomidou.mybatisplus.generator.config.querys;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Sybase库表信息查询
+ *
+ * @author lroyia
+ * @since 2022/1/19 17:08
+ **/
+public class SybaseQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "select name TABLE_NAME, '' TABLE_COMMENT from sysobjects ";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "select o.name TABLE_NAME, c.name FIELD_NAME, upper(t.name) as FIELD_TYPE, " +
+            "(CONVERT(varchar(10),c.id)+ '_' + CONVERT(varchar(10), c.colid)) FIELD_KEY, " +
+            "c.length as COL_LENGTH, c.status FIELD_STATUS, '' FIELD_COMMENT, c.colid SORT_INDEX " +
+            "FROM syscolumns c left join systypes t " +
+            "on c.usertype=t.usertype " +
+            "inner join sysobjects o " +
+            "on c.id=o.id and o.type='U' " +
+            "WHERE o.name = '%s' " +
+            "ORDER BY c.colid";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+    @Override
+    public String tableComment() {
+        return "TABLE_COMMENT";
+    }
+
+    @Override
+    public String fieldName() {
+        return "FIELD_NAME";
+    }
+
+    @Override
+    public String fieldType() {
+        return "FIELD_TYPE";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "FIELD_COMMENT";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "FIELD_KEY";
+    }
+
+    @Override
+    public boolean isKeyIdentity(ResultSet results) throws SQLException {
+        // TODO:目前没有找到准确的判断方式,如果有大佬知道,请补充
+        return results.getInt("SORT_INDEX") == 1 && results.getInt("FIELD_STATUS") == 0;
+    }
+}

+ 67 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/XuguQuery.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.querys;
+
+/**
+ * <p>
+ * Xugu 表数据查询
+ * </p>
+ *
+ * @author unique1319 lanjerry
+ * @since 2020-10-26
+ */
+public class XuguQuery extends AbstractDbQuery {
+
+    @Override
+    public String tablesSql() {
+        return "SELECT * FROM ALL_TABLES WHERE 1 = 1";
+    }
+
+    @Override
+    public String tableFieldsSql() {
+        return "SELECT B.COL_NAME,B.TYPE_NAME,B.COMMENTS, '' AS KEY FROM ALL_TABLES A INNER JOIN ALL_COLUMNS B ON A.TABLE_ID = B.TABLE_ID WHERE A.TABLE_NAME = '%s'";
+    }
+
+    @Override
+    public String tableName() {
+        return "TABLE_NAME";
+    }
+
+    @Override
+    public String tableComment() {
+        return "COMMENTS";
+    }
+
+    @Override
+    public String fieldName() {
+        return "COL_NAME";
+    }
+
+    @Override
+    public String fieldType() {
+        return "TYPE_NAME";
+    }
+
+    @Override
+    public String fieldComment() {
+        return "COMMENTS";
+    }
+
+    @Override
+    public String fieldKey() {
+        return "KEY";
+    }
+}

+ 19 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/package-info.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 代码生成器,数据库查询相关类
+ */
+package com.baomidou.mybatisplus.generator.config.querys;

+ 38 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DateType.java

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.rules;
+
+/**
+ * 数据库时间类型 到 实体类时间类型 对应策略
+ *
+ * @author miemie
+ * @since 2018/5/22
+ */
+public enum DateType {
+    /**
+     * 只使用 java.util.date 代替
+     */
+    ONLY_DATE,
+    /**
+     * 使用 java.sql 包下的
+     */
+    SQL_PACK,
+    /**
+     * 使用 java.time 包下的
+     * <p>java8 新的时间类型</p>
+     */
+    TIME_PACK
+}

+ 93 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbColumnType.java

@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.rules;
+
+/**
+ * 表字段类型
+ *
+ * @author hubin
+ * @since 2017-01-11
+ */
+public enum DbColumnType implements IColumnType {
+    // 基本类型
+    BASE_BYTE("byte", null),
+    BASE_SHORT("short", null),
+    BASE_CHAR("char", null),
+    BASE_INT("int", null),
+    BASE_LONG("long", null),
+    BASE_FLOAT("float", null),
+    BASE_DOUBLE("double", null),
+    BASE_BOOLEAN("boolean", null),
+
+    // 包装类型
+    BYTE("Byte", null),
+    SHORT("Short", null),
+    CHARACTER("Character", null),
+    INTEGER("Integer", null),
+    LONG("Long", null),
+    FLOAT("Float", null),
+    DOUBLE("Double", null),
+    BOOLEAN("Boolean", null),
+    STRING("String", null),
+
+    // sql 包下数据类型
+    DATE_SQL("Date", "java.sql.Date"),
+    TIME("Time", "java.sql.Time"),
+    TIMESTAMP("Timestamp", "java.sql.Timestamp"),
+    BLOB("Blob", "java.sql.Blob"),
+    CLOB("Clob", "java.sql.Clob"),
+
+    // java8 新时间类型
+    LOCAL_DATE("LocalDate", "java.time.LocalDate"),
+    LOCAL_TIME("LocalTime", "java.time.LocalTime"),
+    YEAR("Year", "java.time.Year"),
+    YEAR_MONTH("YearMonth", "java.time.YearMonth"),
+    LOCAL_DATE_TIME("LocalDateTime", "java.time.LocalDateTime"),
+    INSTANT("Instant", "java.time.Instant"),
+
+    // 其他杂类
+    MAP("Map", "java.util.Map"),
+    BYTE_ARRAY("byte[]", null),
+    OBJECT("Object", null),
+    DATE("Date", "java.util.Date"),
+    BIG_INTEGER("BigInteger", "java.math.BigInteger"),
+    BIG_DECIMAL("BigDecimal", "java.math.BigDecimal");
+
+    /**
+     * 类型
+     */
+    private final String type;
+
+    /**
+     * 包路径
+     */
+    private final String pkg;
+
+    DbColumnType(final String type, final String pkg) {
+        this.type = type;
+        this.pkg = pkg;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    @Override
+    public String getPkg() {
+        return pkg;
+    }
+}

+ 39 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/IColumnType.java

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.rules;
+
+/**
+ * 获取实体类字段属性类信息接口
+ *
+ * @author miemie
+ * @since 2018-08-22
+ */
+public interface IColumnType {
+
+    /**
+     * 获取字段类型
+     *
+     * @return 字段类型
+     */
+    String getType();
+
+    /**
+     * 获取字段类型完整名
+     *
+     * @return 字段类型完整名
+     */
+    String getPkg();
+}

+ 142 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/NamingStrategy.java

@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.config.rules;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * 从数据库表到文件的命名策略
+ *
+ * @author YangHu, tangguo
+ * @since 2016/8/30
+ */
+public enum NamingStrategy {
+
+    /**
+     * 不做任何改变,原样输出
+     */
+    no_change,
+
+    /**
+     * 下划线转驼峰命名
+     */
+    underline_to_camel;
+
+    /**
+     * 下划线转驼峰
+     *
+     * @param name 待转内容
+     */
+    public static String underlineToCamel(String name) {
+        // 快速检查
+        if (StringUtils.isBlank(name)) {
+            // 没必要转换
+            return StringPool.EMPTY;
+        }
+        String tempName = name;
+        // 大写数字下划线组成转为小写 , 允许混合模式转为小写
+        if (StringUtils.isCapitalMode(name) || StringUtils.isMixedMode(name)) {
+            tempName = name.toLowerCase();
+        }
+        StringBuilder result = new StringBuilder();
+        // 用下划线将原始字符串分割
+        String[] camels = tempName.split(ConstVal.UNDERLINE);
+        // 跳过原始字符串中开头、结尾的下换线或双重下划线
+        // 处理真正的驼峰片段
+        Arrays.stream(camels).filter(camel -> !StringUtils.isBlank(camel)).forEach(camel -> {
+            if (result.length() == 0) {
+                // 第一个驼峰片段,首字母都小写
+                result.append(StringUtils.firstToLowerCase(camel));
+            } else {
+                // 其他的驼峰片段,首字母大写
+                result.append(capitalFirst(camel));
+            }
+        });
+        return result.toString();
+    }
+
+    /**
+     * 去掉指定的前缀
+     *
+     * @param name   表名
+     * @param prefix 前缀
+     * @return 转换后的字符串
+     */
+    public static String removePrefix(String name, Set<String> prefix) {
+        if (StringUtils.isBlank(name)) {
+            return StringPool.EMPTY;
+        }
+        // 判断是否有匹配的前缀,然后截取前缀
+        return prefix.stream().filter(pf -> name.toLowerCase().startsWith(pf.toLowerCase()))
+            .findFirst().map(pf -> name.substring(pf.length())).orElse(name);
+    }
+
+    /**
+     * 去掉下划线前缀并转成驼峰格式
+     *
+     * @param name   表名
+     * @param prefix 前缀
+     * @return 转换后的字符串
+     */
+    public static String removePrefixAndCamel(String name, Set<String> prefix) {
+        return underlineToCamel(removePrefix(name, prefix));
+    }
+
+    /**
+     * 去掉指定的后缀
+     *
+     * @param name   表名
+     * @param suffix 后缀
+     * @return 转换后的字符串
+     */
+    public static String removeSuffix(String name, Set<String> suffix) {
+        if (StringUtils.isBlank(name)) {
+            return StringPool.EMPTY;
+        }
+        // 判断是否有匹配的后缀,然后截取后缀
+        return suffix.stream().filter(sf -> name.toLowerCase().endsWith(sf.toLowerCase()))
+            .findFirst().map(sf -> name.substring(0, name.length() - sf.length())).orElse(name);
+    }
+
+    /**
+     * 去掉下划线后缀并转成驼峰格式
+     *
+     * @param name   表名
+     * @param suffix 后缀
+     * @return 转换后的字符串
+     */
+    public static String removeSuffixAndCamel(String name, Set<String> suffix) {
+        return underlineToCamel(removeSuffix(name, suffix));
+    }
+
+    /**
+     * 实体首字母大写
+     *
+     * @param name 待转换的字符串
+     * @return 转换后的字符串
+     */
+    public static String capitalFirst(String name) {
+        if (StringUtils.isNotBlank(name)) {
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        return StringPool.EMPTY;
+    }
+}

+ 19 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/package-info.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 代码生成器,规则相关类
+ */
+package com.baomidou.mybatisplus.generator.config.rules;

+ 373 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/AbstractTemplateEngine.java

@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.engine;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.util.FileUtils;
+import com.baomidou.mybatisplus.generator.util.RuntimeUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+
+
+/**
+ * 模板引擎抽象类
+ *
+ * @author hubin
+ * @since 2018-01-10
+ */
+public abstract class AbstractTemplateEngine {
+
+    protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 配置信息
+     */
+    private ConfigBuilder configBuilder;
+
+    /**
+     * 模板引擎初始化
+     */
+    @NotNull
+    public abstract AbstractTemplateEngine init(@NotNull ConfigBuilder configBuilder);
+
+    /**
+     * 输出自定义模板文件
+     *
+     * @param customFiles 自定义模板文件列表
+     * @param tableInfo   表信息
+     * @param objectMap   渲染数据
+     * @since 3.5.3
+     */
+    protected void outputCustomFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
+        String entityName = tableInfo.getEntityName();
+        String parentPath = getPathInfo(OutputFile.parent);
+        customFiles.forEach(file -> {
+            String filePath = StringUtils.isNotBlank(file.getFilePath()) ? file.getFilePath() : parentPath;
+            if (StringUtils.isNotBlank(file.getPackageName())) {
+                filePath = filePath + File.separator + file.getPackageName();
+                filePath = filePath.replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
+            }
+            String fileName = filePath + File.separator + entityName + file.getFileName();
+            outputFile(new File(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
+        });
+    }
+
+    /**
+     * 输出实体文件
+     *
+     * @param tableInfo 表信息
+     * @param objectMap 渲染数据
+     * @since 3.5.0
+     */
+    protected void outputEntity(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
+        String entityName = tableInfo.getEntityName();
+        String entityPath = getPathInfo(OutputFile.entity);
+        if (StringUtils.isNotBlank(entityName) && StringUtils.isNotBlank(entityPath)) {
+            getTemplateFilePath(template -> template.getEntity(getConfigBuilder().getGlobalConfig().isKotlin())).ifPresent((entity) -> {
+                String entityFile = String.format((entityPath + File.separator + "%s" + suffixJavaOrKt()), entityName);
+                outputFile(new File(entityFile), objectMap, entity, getConfigBuilder().getStrategyConfig().entity().isFileOverride());
+            });
+        }
+    }
+
+    /**
+     * 输出Mapper文件(含xml)
+     *
+     * @param tableInfo 表信息
+     * @param objectMap 渲染数据
+     * @since 3.5.0
+     */
+    protected void outputMapper(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
+        // MpMapper.java
+        String entityName = tableInfo.getEntityName();
+        String mapperPath = getPathInfo(OutputFile.mapper);
+        if (StringUtils.isNotBlank(tableInfo.getMapperName()) && StringUtils.isNotBlank(mapperPath)) {
+            getTemplateFilePath(TemplateConfig::getMapper).ifPresent(mapper -> {
+                String mapperFile = String.format((mapperPath + File.separator + tableInfo.getMapperName() + suffixJavaOrKt()), entityName);
+                outputFile(new File(mapperFile), objectMap, mapper, getConfigBuilder().getStrategyConfig().mapper().isFileOverride());
+            });
+        }
+        // MpMapper.xml
+        String xmlPath = getPathInfo(OutputFile.xml);
+        if (StringUtils.isNotBlank(tableInfo.getXmlName()) && StringUtils.isNotBlank(xmlPath)) {
+            getTemplateFilePath(TemplateConfig::getXml).ifPresent(xml -> {
+                String xmlFile = String.format((xmlPath + File.separator + tableInfo.getXmlName() + ConstVal.XML_SUFFIX), entityName);
+                outputFile(new File(xmlFile), objectMap, xml, getConfigBuilder().getStrategyConfig().mapper().isFileOverride());
+            });
+        }
+    }
+
+    /**
+     * 输出service文件
+     *
+     * @param tableInfo 表信息
+     * @param objectMap 渲染数据
+     * @since 3.5.0
+     */
+    protected void outputService(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
+        // IMpService.java
+        String entityName = tableInfo.getEntityName();
+        String servicePath = getPathInfo(OutputFile.service);
+        if (StringUtils.isNotBlank(tableInfo.getServiceName()) && StringUtils.isNotBlank(servicePath)) {
+            getTemplateFilePath(TemplateConfig::getService).ifPresent(service -> {
+                String serviceFile = String.format((servicePath + File.separator + tableInfo.getServiceName() + suffixJavaOrKt()), entityName);
+                outputFile(new File(serviceFile), objectMap, service, getConfigBuilder().getStrategyConfig().service().isFileOverride());
+            });
+        }
+        // MpServiceImpl.java
+        String serviceImplPath = getPathInfo(OutputFile.serviceImpl);
+        if (StringUtils.isNotBlank(tableInfo.getServiceImplName()) && StringUtils.isNotBlank(serviceImplPath)) {
+            getTemplateFilePath(TemplateConfig::getServiceImpl).ifPresent(serviceImpl -> {
+                String implFile = String.format((serviceImplPath + File.separator + tableInfo.getServiceImplName() + suffixJavaOrKt()), entityName);
+                outputFile(new File(implFile), objectMap, serviceImpl, getConfigBuilder().getStrategyConfig().service().isFileOverride());
+            });
+        }
+    }
+
+    /**
+     * 输出controller文件
+     *
+     * @param tableInfo 表信息
+     * @param objectMap 渲染数据
+     * @since 3.5.0
+     */
+    protected void outputController(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
+        // MpController.java
+        String controllerPath = getPathInfo(OutputFile.controller);
+        if (StringUtils.isNotBlank(tableInfo.getControllerName()) && StringUtils.isNotBlank(controllerPath)) {
+            getTemplateFilePath(TemplateConfig::getController).ifPresent(controller -> {
+                String entityName = tableInfo.getEntityName();
+                String controllerFile = String.format((controllerPath + File.separator + tableInfo.getControllerName() + suffixJavaOrKt()), entityName);
+                outputFile(new File(controllerFile), objectMap, controller, getConfigBuilder().getStrategyConfig().controller().isFileOverride());
+            });
+        }
+    }
+
+    /**
+     * 输出文件
+     *
+     * @param file         文件
+     * @param objectMap    渲染信息
+     * @param templatePath 模板路径
+     * @param fileOverride 是否覆盖已有文件
+     * @since 3.5.2
+     */
+    protected void outputFile(@NotNull File file, @NotNull Map<String, Object> objectMap, @NotNull String templatePath, boolean fileOverride) {
+        if (isCreate(file, fileOverride)) {
+            try {
+                // 全局判断【默认】
+                boolean exist = file.exists();
+                if (!exist) {
+                    File parentFile = file.getParentFile();
+                    FileUtils.forceMkdir(parentFile);
+                }
+                writer(objectMap, templatePath, file);
+            } catch (Exception exception) {
+                throw new RuntimeException(exception);
+            }
+        }
+    }
+
+    /**
+     * 获取模板路径
+     *
+     * @param function function
+     * @return 模板路径
+     * @since 3.5.0
+     */
+    @NotNull
+    protected Optional<String> getTemplateFilePath(@NotNull Function<TemplateConfig, String> function) {
+        TemplateConfig templateConfig = getConfigBuilder().getTemplateConfig();
+        String filePath = function.apply(templateConfig);
+        if (StringUtils.isNotBlank(filePath)) {
+            return Optional.of(templateFilePath(filePath));
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * 获取路径信息
+     *
+     * @param outputFile 输出文件
+     * @return 路径信息
+     */
+    @Nullable
+    protected String getPathInfo(@NotNull OutputFile outputFile) {
+        return getConfigBuilder().getPathInfo().get(outputFile);
+    }
+
+    /**
+     * 批量输出 java xml 文件
+     */
+    @NotNull
+    public AbstractTemplateEngine batchOutput() {
+        try {
+            ConfigBuilder config = this.getConfigBuilder();
+            List<TableInfo> tableInfoList = config.getTableInfoList();
+            tableInfoList.forEach(tableInfo -> {
+                Map<String, Object> objectMap = this.getObjectMap(config, tableInfo);
+                Optional.ofNullable(config.getInjectionConfig()).ifPresent(t -> {
+                    // 添加自定义属性
+                    t.beforeOutputFile(tableInfo, objectMap);
+                    // 输出自定义文件
+                    outputCustomFile(t.getCustomFiles(), tableInfo, objectMap);
+                });
+                // entity
+                outputEntity(tableInfo, objectMap);
+                // mapper and xml
+                outputMapper(tableInfo, objectMap);
+                // service
+                outputService(tableInfo, objectMap);
+                // controller
+                outputController(tableInfo, objectMap);
+            });
+        } catch (Exception e) {
+            throw new RuntimeException("无法创建文件,请检查配置信息!", e);
+        }
+        return this;
+    }
+
+    /**
+     * 将模板转化成为文件
+     *
+     * @param objectMap    渲染对象 MAP 信息
+     * @param templatePath 模板文件
+     * @param outputFile   文件生成的目录
+     * @throws Exception 异常
+     * @since 3.5.0
+     */
+//    public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
+//        this.writer(objectMap, templatePath, outputFile.getPath());
+//        logger.debug("模板:" + templatePath + ";  文件:" + outputFile);
+//    }
+    @NotNull
+    public abstract void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception;
+
+    /**
+     * 打开输出目录
+     */
+    public void open() {
+        String outDir = getConfigBuilder().getGlobalConfig().getOutputDir();
+        if (StringUtils.isBlank(outDir) || !new File(outDir).exists()) {
+            System.err.println("未找到输出目录:" + outDir);
+        } else if (getConfigBuilder().getGlobalConfig().isOpen()) {
+            try {
+                RuntimeUtils.openDir(outDir);
+            } catch (IOException e) {
+                LOGGER.error(e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * 渲染对象 MAP 信息
+     *
+     * @param config    配置信息
+     * @param tableInfo 表信息对象
+     * @return ignore
+     */
+    @NotNull
+    public Map<String, Object> getObjectMap(@NotNull ConfigBuilder config, @NotNull TableInfo tableInfo) {
+        StrategyConfig strategyConfig = config.getStrategyConfig();
+        Map<String, Object> controllerData = strategyConfig.controller().renderData(tableInfo);
+        Map<String, Object> objectMap = new HashMap<>(controllerData);
+        Map<String, Object> mapperData = strategyConfig.mapper().renderData(tableInfo);
+        objectMap.putAll(mapperData);
+        Map<String, Object> serviceData = strategyConfig.service().renderData(tableInfo);
+        objectMap.putAll(serviceData);
+        Map<String, Object> entityData = strategyConfig.entity().renderData(tableInfo);
+        objectMap.putAll(entityData);
+        objectMap.put("config", config);
+        objectMap.put("package", config.getPackageConfig().getPackageInfo());
+        GlobalConfig globalConfig = config.getGlobalConfig();
+        objectMap.put("author", globalConfig.getAuthor());
+        objectMap.put("kotlin", globalConfig.isKotlin());
+        objectMap.put("swagger", globalConfig.isSwagger());
+        objectMap.put("springdoc", globalConfig.isSpringdoc());
+        objectMap.put("date", globalConfig.getCommentDate());
+        // 启用 schema 处理逻辑
+        String schemaName = "";
+        if (strategyConfig.isEnableSchema()) {
+            // 存在 schemaName 设置拼接 . 组合表名
+            schemaName = config.getDataSourceConfig().getSchemaName();
+            if (StringUtils.isNotBlank(schemaName)) {
+                schemaName += ".";
+                tableInfo.setConvert(true);
+            }
+        }
+        objectMap.put("schemaName", schemaName);
+        objectMap.put("table", tableInfo);
+        objectMap.put("entity", tableInfo.getEntityName());
+        return objectMap;
+    }
+
+    /**
+     * 模板真实文件路径
+     *
+     * @param filePath 文件路径
+     * @return ignore
+     */
+    @NotNull
+    public abstract String templateFilePath(@NotNull String filePath);
+
+    /**
+     * 检查文件是否创建文件
+     *
+     * @param file         文件
+     * @param fileOverride 是否覆盖已有文件
+     * @return 是否创建文件
+     * @since 3.5.2
+     */
+    protected boolean isCreate(@NotNull File file, boolean fileOverride) {
+        if (file.exists() && !fileOverride) {
+            LOGGER.warn("文件[{}]已存在,且未开启文件覆盖配置,需要开启配置可到策略配置中设置!!!", file.getName());
+        }
+        return !file.exists() || fileOverride;
+    }
+
+    /**
+     * 文件后缀
+     */
+    protected String suffixJavaOrKt() {
+        return getConfigBuilder().getGlobalConfig().isKotlin() ? ConstVal.KT_SUFFIX : ConstVal.JAVA_SUFFIX;
+    }
+
+    @NotNull
+    public ConfigBuilder getConfigBuilder() {
+        return configBuilder;
+    }
+
+    @NotNull
+    public AbstractTemplateEngine setConfigBuilder(@NotNull ConfigBuilder configBuilder) {
+        this.configBuilder = configBuilder;
+        return this;
+    }
+}

+ 82 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/BeetlTemplateEngine.java

@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.engine;
+
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import org.beetl.core.Configuration;
+import org.beetl.core.GroupTemplate;
+import org.beetl.core.Template;
+import org.beetl.core.resource.ClasspathResourceLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * Beetl 模板引擎实现文件输出
+ *
+ * @author yandixuan
+ * @since 2018-12-16
+ */
+public class BeetlTemplateEngine extends AbstractTemplateEngine {
+
+    private static Method method;
+
+    static {
+        try {
+            method = GroupTemplate.class.getDeclaredMethod("getTemplate", Object.class);
+        } catch (NoSuchMethodException e) {
+            try {
+                //3.2.x 方法签名修改成了object,其他低版本为string
+                method = GroupTemplate.class.getDeclaredMethod("getTemplate", String.class);
+            } catch (NoSuchMethodException exception) {
+                throw new RuntimeException(exception);
+            }
+        }
+    }
+
+    private GroupTemplate groupTemplate;
+
+    @Override
+    public @NotNull AbstractTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
+        try {
+            Configuration cfg = Configuration.defaultConfiguration();
+            groupTemplate = new GroupTemplate(new ClasspathResourceLoader("/"), cfg);
+        } catch (IOException e) {
+            LOGGER.error("初始化模板引擎失败:", e);
+            throw new RuntimeException(e);
+        }
+        return this;
+    }
+
+    @Override
+    public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
+        Template template = (Template) method.invoke(groupTemplate, templatePath);
+        try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
+            template.binding(objectMap);
+            template.renderTo(fileOutputStream);
+        }
+        LOGGER.debug("模板:" + templatePath + ";  文件:" + outputFile);
+    }
+
+    @Override
+    public @NotNull String templateFilePath(@NotNull String filePath) {
+        return filePath + ".btl";
+    }
+}

+ 49 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/EnjoyTemplateEngine.java

@@ -0,0 +1,49 @@
+package com.baomidou.mybatisplus.generator.engine;
+
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.jfinal.template.Engine;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Map;
+
+/**
+ * enjoy 模板引擎实现文件输出
+ *
+ * @author flyinke
+ * @since 2022-06-16
+ */
+public class EnjoyTemplateEngine extends AbstractTemplateEngine {
+
+    private Engine engine;
+
+    @Override
+    public @NotNull AbstractTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
+        engine = Engine.createIfAbsent("mybatis-plus-generator", e -> {
+            e.setToClassPathSourceFactory();
+        });
+        return this;
+    }
+
+    @Override
+    public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
+        String str = engine.getTemplate(templatePath).renderToString(objectMap);
+        try (FileOutputStream fos = new FileOutputStream(outputFile);
+             OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
+             BufferedWriter writer = new BufferedWriter(ow)) {
+            writer.append(str);
+        }
+        LOGGER.debug("模板:" + templatePath + ";  文件:" + outputFile);
+    }
+
+    @Override
+    public @NotNull String templateFilePath(@NotNull String filePath) {
+        final String dotVm = ".ej";
+        return filePath.endsWith(dotVm) ? filePath : filePath + dotVm;
+    }
+}
+

+ 62 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/FreemarkerTemplateEngine.java

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.engine;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Map;
+
+/**
+ * Freemarker 模板引擎实现文件输出
+ *
+ * @author nieqiurong
+ * @since 2018-01-11
+ */
+public class FreemarkerTemplateEngine extends AbstractTemplateEngine {
+    private Configuration configuration;
+
+    @Override
+    public @NotNull FreemarkerTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
+        configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+        configuration.setDefaultEncoding(ConstVal.UTF8);
+        configuration.setClassForTemplateLoading(FreemarkerTemplateEngine.class, StringPool.SLASH);
+        return this;
+    }
+
+
+    @Override
+    public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
+        Template template = configuration.getTemplate(templatePath);
+        try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
+            template.process(objectMap, new OutputStreamWriter(fileOutputStream, ConstVal.UTF8));
+        }
+        LOGGER.debug("模板:" + templatePath + ";  文件:" + outputFile);
+    }
+
+
+    @Override
+    public @NotNull String templateFilePath(@NotNull String filePath) {
+        return filePath + ".ftl";
+    }
+}

+ 84 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/VelocityTemplateEngine.java

@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.engine;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.app.VelocityEngine;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Velocity 模板引擎实现文件输出
+ *
+ * @author hubin
+ * @since 2018-01-10
+ */
+public class VelocityTemplateEngine extends AbstractTemplateEngine {
+    private VelocityEngine velocityEngine;
+
+    {
+        try {
+            Class.forName("org.apache.velocity.util.DuckType");
+        } catch (ClassNotFoundException e) {
+            // velocity1.x的生成格式错乱 https://github.com/baomidou/generator/issues/5
+            LOGGER.warn("Velocity 1.x is outdated, please upgrade to 2.x or later.");
+        }
+    }
+
+    @Override
+    public @NotNull VelocityTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
+        if (null == velocityEngine) {
+            Properties p = new Properties();
+            p.setProperty(ConstVal.VM_LOAD_PATH_KEY, ConstVal.VM_LOAD_PATH_VALUE);
+            p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, StringPool.EMPTY);
+            p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
+            p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
+            p.setProperty("file.resource.loader.unicode", StringPool.TRUE);
+            velocityEngine = new VelocityEngine(p);
+        }
+        return this;
+    }
+
+
+    @Override
+    public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
+        Template template = velocityEngine.getTemplate(templatePath, ConstVal.UTF8);
+        try (FileOutputStream fos = new FileOutputStream(outputFile);
+             OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
+             BufferedWriter writer = new BufferedWriter(ow)) {
+            template.merge(new VelocityContext(objectMap), writer);
+        }
+        LOGGER.debug("模板:" + templatePath + ";  文件:" + outputFile);
+    }
+
+
+    @Override
+    public @NotNull String templateFilePath(@NotNull String filePath) {
+        final String dotVm = ".vm";
+        return filePath.endsWith(dotVm) ? filePath : filePath + dotVm;
+    }
+}

+ 53 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/fill/Column.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.fill;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.generator.IFill;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 字段填充
+ *
+ * @author nieqiurong
+ * @since 3.5.0 2020/12/1.
+ */
+public class Column implements IFill {
+
+    private final String columnName;
+
+    private final FieldFill fieldFill;
+
+    public Column(@NotNull String columnName, @NotNull FieldFill fieldFill) {
+        this.columnName = columnName;
+        this.fieldFill = fieldFill;
+    }
+
+    public Column(String columnName) {
+        this.columnName = columnName;
+        this.fieldFill = FieldFill.DEFAULT;
+    }
+
+    @Override
+    public @NotNull String getName() {
+        return this.columnName;
+    }
+
+    @Override
+    public @NotNull FieldFill getFieldFill() {
+        return this.fieldFill;
+    }
+}

+ 53 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/fill/Property.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.fill;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.generator.IFill;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 属性填充
+ *
+ * @author nieqiurong
+ * @since 3.5.0 2020/11/30.
+ */
+public class Property implements IFill {
+
+    private final String propertyName;
+
+    private final FieldFill fieldFill;
+
+    public Property(@NotNull String propertyName, @NotNull FieldFill fieldFill) {
+        this.propertyName = propertyName;
+        this.fieldFill = fieldFill;
+    }
+
+    public Property(@NotNull String propertyName) {
+        this.propertyName = propertyName;
+        this.fieldFill = FieldFill.DEFAULT;
+    }
+
+    @Override
+    public @NotNull String getName() {
+        return this.propertyName;
+    }
+
+    @Override
+    public @NotNull FieldFill getFieldFill() {
+        return this.fieldFill;
+    }
+}

+ 32 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/function/ConverterFileName.java

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.function;
+
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 转换输出文件名称
+ *
+ * @author nieqiurong 2020/11/05.
+ * @since 3.5.0
+ */
+@FunctionalInterface
+public interface ConverterFileName {
+
+    @NotNull
+    String convert(String entityName);
+}

+ 238 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/jdbc/DatabaseMetaDataWrapper.java

@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.jdbc;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import org.apache.ibatis.type.JdbcType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+
+/**
+ * 数据库数据元包装类
+ *
+ * @author nieqiurong 2021/2/8.
+ * @since 3.5.0
+ */
+public class DatabaseMetaDataWrapper {
+
+    private static final Logger logger = LoggerFactory.getLogger(DatabaseMetaDataWrapper.class);
+
+    private final DatabaseMetaData databaseMetaData;
+
+    //TODO 暂时只支持一种
+    private final String catalog;
+
+    //TODO 暂时只支持一种
+    private final String schema;
+
+    public DatabaseMetaDataWrapper(DataSourceConfig dataSourceConfig) {
+        try {
+            Connection connection = dataSourceConfig.getConn();
+            this.databaseMetaData = connection.getMetaData();
+            this.catalog = connection.getCatalog();
+            this.schema = dataSourceConfig.getSchemaName();
+        } catch (SQLException e) {
+            throw new RuntimeException("获取元数据错误:", e);
+        }
+    }
+
+    public Map<String, Column> getColumnsInfo(String tableNamePattern, boolean queryPrimaryKey) {
+        return getColumnsInfo(this.catalog, this.schema, tableNamePattern, queryPrimaryKey);
+    }
+
+    /**
+     * 获取表字段信息
+     *
+     * @return 表字段信息 (小写字段名->字段信息)
+     */
+    public Map<String, Column> getColumnsInfo(String catalog, String schema, String tableName, boolean queryPrimaryKey) {
+        Set<String> primaryKeys = new HashSet<>();
+        if (queryPrimaryKey) {
+            try (ResultSet primaryKeysResultSet = databaseMetaData.getPrimaryKeys(catalog, schema, tableName)) {
+                while (primaryKeysResultSet.next()) {
+                    String columnName = primaryKeysResultSet.getString("COLUMN_NAME");
+                    primaryKeys.add(columnName);
+                }
+                if (primaryKeys.size() > 1) {
+                    logger.warn("当前表:{},存在多主键情况!", tableName);
+                }
+            } catch (SQLException e) {
+                throw new RuntimeException("读取表主键信息:" + tableName + "错误:", e);
+            }
+        }
+        Map<String, Column> columnsInfoMap = new LinkedHashMap<>();
+        try (ResultSet resultSet = databaseMetaData.getColumns(catalog, schema, tableName, "%")) {
+            while (resultSet.next()) {
+                Column column = new Column();
+                String name = resultSet.getString("COLUMN_NAME");
+                column.name = name;
+                column.primaryKey = primaryKeys.contains(name);
+                column.jdbcType = JdbcType.forCode(resultSet.getInt("DATA_TYPE"));
+                column.length = resultSet.getInt("COLUMN_SIZE");
+                column.scale = resultSet.getInt("DECIMAL_DIGITS");
+                column.remarks = formatComment(resultSet.getString("REMARKS"));
+                column.defaultValue = resultSet.getString("COLUMN_DEF");
+                column.nullable = resultSet.getInt("NULLABLE") == DatabaseMetaData.columnNullable;
+                try {
+                    column.autoIncrement = "YES".equals(resultSet.getString("IS_AUTOINCREMENT"));
+                } catch (SQLException sqlException) {
+                    logger.warn("获取IS_AUTOINCREMENT出现异常:", sqlException);
+                    //TODO 目前测试在oracle旧驱动下存在问题,降级成false.
+                }
+                columnsInfoMap.put(name.toLowerCase(), column);
+            }
+            return Collections.unmodifiableMap(columnsInfoMap);
+        } catch (SQLException e) {
+            throw new RuntimeException("读取表字段信息:" + tableName + "错误:", e);
+        }
+    }
+
+    public String formatComment(String comment) {
+        return StringUtils.isBlank(comment) ? StringPool.EMPTY : comment.replaceAll("\r\n", "\t");
+    }
+
+    public Table getTableInfo(String tableName) {
+        return getTableInfo(this.catalog, this.schema, tableName);
+    }
+
+    public List<Table> getTables(String tableNamePattern, String[] types) {
+        return getTables(this.catalog, this.schema, tableNamePattern, types);
+    }
+
+    public List<Table> getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) {
+        List<Table> tables = new ArrayList<>();
+        try (ResultSet resultSet = databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types)) {
+            Table table;
+            while (resultSet.next()) {
+                table = new Table();
+                table.name = resultSet.getString("TABLE_NAME");
+                table.remarks = formatComment(resultSet.getString("REMARKS"));
+                table.tableType = resultSet.getString("TABLE_TYPE");
+                tables.add(table);
+            }
+        } catch (SQLException e) {
+            throw new RuntimeException("读取数据库表信息出现错误", e);
+        }
+        return tables;
+    }
+
+    public Table getTableInfo(String catalog, String schema, String tableName) {
+        Table table = new Table();
+        //TODO 后面要根据表是否为视图来查询,后面重构表查询策略。
+        try (ResultSet resultSet = databaseMetaData.getTables(catalog, schema, tableName, new String[]{"TABLE", "VIEW"})) {
+            table.name = tableName;
+            while (resultSet.next()) {
+                table.remarks = formatComment(resultSet.getString("REMARKS"));
+                table.tableType = resultSet.getString("TABLE_TYPE");
+            }
+        } catch (SQLException e) {
+            throw new RuntimeException("读取表信息:" + tableName + "错误:", e);
+        }
+        return table;
+    }
+
+    public static class Table {
+
+        private String name;
+
+        private String remarks;
+
+        private String tableType;
+
+        public String getRemarks() {
+            return remarks;
+        }
+
+        public String getTableType() {
+            return tableType;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public boolean isView() {
+            return "VIEW".equals(tableType);
+        }
+
+    }
+
+    public static class Column {
+
+        private boolean primaryKey;
+
+        private boolean autoIncrement;
+
+        private String name;
+
+        private int length;
+
+        private boolean nullable;
+
+        private String remarks;
+
+        private String defaultValue;
+
+        private int scale;
+
+        private JdbcType jdbcType;
+
+        public String getName() {
+            return name;
+        }
+
+        public int getLength() {
+            return length;
+        }
+
+        public boolean isNullable() {
+            return nullable;
+        }
+
+        public String getRemarks() {
+            return remarks;
+        }
+
+        public String getDefaultValue() {
+            return defaultValue;
+        }
+
+        public int getScale() {
+            return scale;
+        }
+
+        public JdbcType getJdbcType() {
+            return jdbcType;
+        }
+
+        public boolean isPrimaryKey() {
+            return primaryKey;
+        }
+
+        public boolean isAutoIncrement() {
+            return autoIncrement;
+        }
+
+    }
+}

+ 55 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/BaseKeyWordsHandler.java

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.keywords;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.baomidou.mybatisplus.generator.config.IKeyWordsHandler;
+
+/**
+ * 基类关键字处理
+ *
+ * @author nieqiurong 2020/5/8.
+ * @since 3.3.2
+ */
+public abstract class BaseKeyWordsHandler implements IKeyWordsHandler {
+
+    public Set<String> keyWords;
+
+    public BaseKeyWordsHandler(@NotNull List<String> keyWords) {
+        this.keyWords = new HashSet<>(keyWords);
+    }
+
+    public BaseKeyWordsHandler(@NotNull Set<String> keyWords) {
+        this.keyWords = keyWords;
+    }
+
+    @Override
+    public @NotNull Collection<String> getKeyWords() {
+        return keyWords;
+    }
+
+    @Override
+    public boolean isKeyWords(@NotNull String columnName) {
+        return getKeyWords().contains(columnName.toUpperCase(Locale.ENGLISH));
+    }
+}

+ 135 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/H2KeyWordsHandler.java

@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.keywords;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * h2数据库关键字处理
+ * http://www.h2database.com/html/advanced.html#keywords
+ *
+ * @author nieqiurong 2020/5/7.
+ * @since 3.3.2
+ */
+public class H2KeyWordsHandler extends BaseKeyWordsHandler {
+
+    private static final List<String> KEY_WORDS = new ArrayList<>(Arrays.asList(
+        "ALL",
+        "AND",
+        "ARRAY",
+        "AS",
+        "BETWEEN",
+        "BOTH",
+        "CASE",
+        "CHECK",
+        "CONSTRAINT",
+        "CROSS",
+        "CURRENT_CATALOG",
+        "CURRENT_DATE",
+        "CURRENT_SCHEMA",
+        "CURRENT_TIME",
+        "CURRENT_TIMESTAMP",
+        "CURRENT_USER",
+        "DISTINCT",
+        "EXCEPT",
+        "EXISTS",
+        "FALSE",
+        "FETCH",
+        "FILTER",
+        "FOR",
+        "FOREIGN",
+        "FROM",
+        "FULL",
+        "GROUP",
+        "GROUPS",
+        "HAVING",
+        "IF",
+        "ILIKE",
+        "IN",
+        "INNER",
+        "INTERSECT",
+        "INTERSECTS",
+        "INTERVAL",
+        "IS",
+        "JOIN",
+        "LEADING",
+        "LEFT",
+        "LIKE",
+        "LIMIT",
+        "LOCALTIME",
+        "LOCALTIMESTAMP",
+        "MINUS",
+        "NATURAL",
+        "NOT",
+        "NULL",
+        "OFFSET",
+        "ON",
+        "OR",
+        "ORDER",
+        "OVER",
+        "PARTITION",
+        "PRIMARY",
+        "QUALIFY",
+        "RANGE",
+        "REGEXP",
+        "RIGHT",
+        "ROW",
+        "_ROWID_",
+        "ROWNUM",
+        "ROWS",
+        "SELECT",
+        "SYSDATE",
+        "SYSTIME",
+        "SYSTIMESTAMP",
+        "TABLE",
+        "TODAY",
+        "TOP",
+        "TRAILING",
+        "TRUE",
+        "UNION",
+        "UNIQUE",
+        "UNKNOWN",
+        "USING",
+        "VALUES",
+        "WHERE",
+        "WINDOW",
+        "WITH"
+    ));
+
+    public H2KeyWordsHandler() {
+        super(new HashSet<>(KEY_WORDS));
+    }
+
+    public H2KeyWordsHandler(@NotNull List<String> keyWords) {
+        super(new HashSet<>(keyWords));
+    }
+
+    public H2KeyWordsHandler(@NotNull Set<String> keyWords) {
+        super(keyWords);
+    }
+
+    @Override
+    public @NotNull String formatStyle() {
+        return "\"%s\"";
+    }
+
+}

+ 808 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/MySqlKeyWordsHandler.java

@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.keywords;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * mysql关键字处理
+ * 这里选取了mysql8.0文档中的关键字和保留字(含移除)https://dev.mysql.com/doc/refman/8.0/en/keywords.html
+ *
+ * @author nieqiurong 2020/5/7.
+ * @since 3.3.2
+ */
+public class MySqlKeyWordsHandler extends BaseKeyWordsHandler {
+
+    private static final List<String> KEY_WORDS = new ArrayList<>(Arrays.asList(
+        "ACCESSIBLE",
+        "ACCOUNT",
+        "ACTION",
+        "ACTIVE",
+        "ADD",
+        "ADMIN",
+        "AFTER",
+        "AGAINST",
+        "AGGREGATE",
+        "ALGORITHM",
+        "ALL",
+        "ALTER",
+        "ALWAYS",
+        "ANALYSE",
+        "ANALYZE",
+        "AND",
+        "ANY",
+        "ARRAY",
+        "AS",
+        "ASC",
+        "ASCII",
+        "ASENSITIVE",
+        "AT",
+        "ATTRIBUTE",
+        "AUTHENTICATION",
+        "AUTOEXTEND_SIZE",
+        "AUTO_INCREMENT",
+        "AVG",
+        "AVG_ROW_LENGTH",
+        "BACKUP",
+        "BEFORE",
+        "BEGIN",
+        "BETWEEN",
+        "BIGINT",
+        "BINARY",
+        "BINLOG",
+        "BIT",
+        "BLOB",
+        "BLOCK",
+        "BOOL",
+        "BOOLEAN",
+        "BOTH",
+        "BTREE",
+        "BUCKETS",
+        "BY",
+        "BYTE",
+        "CACHE",
+        "CALL",
+        "CASCADE",
+        "CASCADED",
+        "CASE",
+        "CATALOG_NAME",
+        "CHAIN",
+        "CHALLENGE_RESPONSE",
+        "CHANGE",
+        "CHANGED",
+        "CHANNEL",
+        "CHAR",
+        "CHARACTER",
+        "CHARSET",
+        "CHECK",
+        "CHECKSUM",
+        "CIPHER",
+        "CLASS_ORIGIN",
+        "CLIENT",
+        "CLONE",
+        "CLOSE",
+        "COALESCE",
+        "CODE",
+        "COLLATE",
+        "COLLATION",
+        "COLUMN",
+        "COLUMNS",
+        "COLUMN_FORMAT",
+        "COLUMN_NAME",
+        "COMMENT",
+        "COMMIT",
+        "COMMITTED",
+        "COMPACT",
+        "COMPLETION",
+        "COMPONENT",
+        "COMPRESSED",
+        "COMPRESSION",
+        "CONCURRENT",
+        "CONDITION",
+        "CONNECTION",
+        "CONSISTENT",
+        "CONSTRAINT",
+        "CONSTRAINT_CATALOG",
+        "CONSTRAINT_NAME",
+        "CONSTRAINT_SCHEMA",
+        "CONTAINS",
+        "CONTEXT",
+        "CONTINUE",
+        "CONVERT",
+        "CPU",
+        "CREATE",
+        "CROSS",
+        "CUBE",
+        "CUME_DIST",
+        "CURRENT",
+        "CURRENT_DATE",
+        "CURRENT_TIME",
+        "CURRENT_TIMESTAMP",
+        "CURRENT_USER",
+        "CURSOR",
+        "CURSOR_NAME",
+        "DATA",
+        "DATABASE",
+        "DATABASES",
+        "DATAFILE",
+        "DATE",
+        "DATETIME",
+        "DAY",
+        "DAY_HOUR",
+        "DAY_MICROSECOND",
+        "DAY_MINUTE",
+        "DAY_SECOND",
+        "DEALLOCATE",
+        "DEC",
+        "DECIMAL",
+        "DECLARE",
+        "DEFAULT",
+        "DEFAULT_AUTH",
+        "DEFINER",
+        "DEFINITION",
+        "DELAYED",
+        "DELAY_KEY_WRITE",
+        "DELETE",
+        "DENSE_RANK",
+        "DESC",
+        "DESCRIBE",
+        "DESCRIPTION",
+        "DES_KEY_FILE",
+        "DETERMINISTIC",
+        "DIAGNOSTICS",
+        "DIRECTORY",
+        "DISABLE",
+        "DISCARD",
+        "DISK",
+        "DISTINCT",
+        "DISTINCTROW",
+        "DIV",
+        "DO",
+        "DOUBLE",
+        "DROP",
+        "DUAL",
+        "DUMPFILE",
+        "DUPLICATE",
+        "DYNAMIC",
+        "EACH",
+        "ELSE",
+        "ELSEIF",
+        "EMPTY",
+        "ENABLE",
+        "ENCLOSED",
+        "ENCRYPTION",
+        "END",
+        "ENDS",
+        "ENFORCED",
+        "ENGINE",
+        "ENGINE_ATTRIBUTE",
+        "ENGINES",
+        "ENUM",
+        "ERROR",
+        "ERRORS",
+        "ESCAPE",
+        "ESCAPED",
+        "EVENT",
+        "EVENTS",
+        "EVERY",
+        "EXCEPT",
+        "EXCHANGE",
+        "EXCLUDE",
+        "EXECUTE",
+        "EXISTS",
+        "EXIT",
+        "EXPANSION",
+        "EXPIRE",
+        "EXPLAIN",
+        "EXPORT",
+        "EXTENDED",
+        "EXTENT_SIZE",
+        "FACTOR",
+        "FAILED_LOGIN_ATTEMPTS",
+        "FALSE",
+        "FAST",
+        "FAULTS",
+        "FETCH",
+        "FIELDS",
+        "FILE",
+        "FILE_BLOCK_SIZE",
+        "FILTER",
+        "FINISH",
+        "FIRST",
+        "FIRST_VALUE",
+        "FIXED",
+        "FLOAT",
+        "FLOAT4",
+        "FLOAT8",
+        "FLUSH",
+        "FOLLOWING",
+        "FOLLOWS",
+        "FOR",
+        "FORCE",
+        "FOREIGN",
+        "FORMAT",
+        "FOUND",
+        "FROM",
+        "FULL",
+        "FULLTEXT",
+        "FUNCTION",
+        "GENERAL",
+        "GENERATED",
+        "GEOMCOLLECTION",
+        "GEOMETRY",
+        "GEOMETRYCOLLECTION",
+        "GET",
+        "GET_FORMAT",
+        "GET_MASTER_PUBLIC_KEY",
+        "GET_SOURCE_PUBLIC_KEY",
+        "GLOBAL",
+        "GRANT",
+        "GRANTS",
+        "GROUP",
+        "GROUP_REPLICATION",
+        "GROUPING",
+        "GROUPS",
+        "GTID_ONLY",
+        "HANDLER",
+        "HASH",
+        "HAVING",
+        "HELP",
+        "HIGH_PRIORITY",
+        "HISTOGRAM",
+        "HISTORY",
+        "HOST",
+        "HOSTS",
+        "HOUR",
+        "HOUR_MICROSECOND",
+        "HOUR_MINUTE",
+        "HOUR_SECOND",
+        "IDENTIFIED",
+        "IF",
+        "IGNORE",
+        "IGNORE_SERVER_IDS",
+        "IMPORT",
+        "IN",
+        "INACTIVE",
+        "INDEX",
+        "INDEXES",
+        "INFILE",
+        "INITIAL",
+        "INITIAL_SIZE",
+        "INITIATE",
+        "INNER",
+        "INOUT",
+        "INSENSITIVE",
+        "INSERT",
+        "INSERT_METHOD",
+        "INSTALL",
+        "INSTANCE",
+        "INT",
+        "INT1",
+        "INT2",
+        "INT3",
+        "INT4",
+        "INT8",
+        "INTEGER",
+        "INTERVAL",
+        "INTO",
+        "INVISIBLE",
+        "INVOKER",
+        "IO",
+        "IO_AFTER_GTIDS",
+        "IO_BEFORE_GTIDS",
+        "IO_THREAD",
+        "IPC",
+        "IS",
+        "ISOLATION",
+        "ISSUER",
+        "ITERATE",
+        "JOIN",
+        "JSON",
+        "JSON_TABLE",
+        "JSON_VALUE",
+        "KEY",
+        "KEYS",
+        "KEY_BLOCK_SIZE",
+        "KEYRING",
+        "KILL",
+        "LAG",
+        "LANGUAGE",
+        "LAST",
+        "LAST_VALUE",
+        "LATERAL",
+        "LEAD",
+        "LEADING",
+        "LEAVE",
+        "LEAVES",
+        "LEFT",
+        "LESS",
+        "LEVEL",
+        "LIKE",
+        "LIMIT",
+        "LINEAR",
+        "LINES",
+        "LINESTRING",
+        "LIST",
+        "LOAD",
+        "LOCAL",
+        "LOCALTIME",
+        "LOCALTIMESTAMP",
+        "LOCK",
+        "LOCKED",
+        "LOCKS",
+        "LOGFILE",
+        "LOGS",
+        "LONG",
+        "LONGBLOB",
+        "LONGTEXT",
+        "LOOP",
+        "LOW_PRIORITY",
+        "MASTER",
+        "MASTER_AUTO_POSITION",
+        "MASTER_BIND",
+        "MASTER_COMPRESSION_ALGORITHMS",
+        "MASTER_CONNECT_RETRY",
+        "MASTER_DELAY",
+        "MASTER_HEARTBEAT_PERIOD",
+        "MASTER_HOST",
+        "MASTER_LOG_FILE",
+        "MASTER_LOG_POS",
+        "MASTER_PASSWORD",
+        "MASTER_PORT",
+        "MASTER_PUBLIC_KEY_PATH",
+        "MASTER_RETRY_COUNT",
+        "MASTER_SERVER_ID",
+        "MASTER_SSL",
+        "MASTER_SSL_CA",
+        "MASTER_SSL_CAPATH",
+        "MASTER_SSL_CERT",
+        "MASTER_SSL_CIPHER",
+        "MASTER_SSL_CRL",
+        "MASTER_SSL_CRLPATH",
+        "MASTER_SSL_KEY",
+        "MASTER_SSL_VERIFY_SERVER_CERT",
+        "MASTER_TLS_CIPHERSUITES",
+        "MASTER_TLS_VERSION",
+        "MASTER_USER",
+        "MASTER_ZSTD_COMPRESSION_LEVEL",
+        "MATCH",
+        "MAXVALUE",
+        "MAX_CONNECTIONS_PER_HOUR",
+        "MAX_QUERIES_PER_HOUR",
+        "MAX_ROWS",
+        "MAX_SIZE",
+        "MAX_STATEMENT_TIME",
+        "MAX_UPDATES_PER_HOUR",
+        "MAX_USER_CONNECTIONS",
+        "MEDIUM",
+        "MEDIUMBLOB",
+        "MEDIUMINT",
+        "MEDIUMTEXT",
+        "MEMBER",
+        "MEMORY",
+        "MERGE",
+        "MESSAGE_TEXT",
+        "MICROSECOND",
+        "MIDDLEINT",
+        "MIGRATE",
+        "MINUTE",
+        "MINUTE_MICROSECOND",
+        "MINUTE_SECOND",
+        "MIN_ROWS",
+        "MOD",
+        "MODE",
+        "MODIFIES",
+        "MODIFY",
+        "MONTH",
+        "MULTILINESTRING",
+        "MULTIPOINT",
+        "MULTIPOLYGON",
+        "MUTEX",
+        "MYSQL_ERRNO",
+        "NAME",
+        "NAMES",
+        "NATIONAL",
+        "NATURAL",
+        "NCHAR",
+        "NDB",
+        "NDBCLUSTER",
+        "NESTED",
+        "NETWORK_NAMESPACE",
+        "NEVER",
+        "NEW",
+        "NEXT",
+        "NO",
+        "NODEGROUP",
+        "NONBLOCKING",
+        "NONE",
+        "NOT",
+        "NOWAIT",
+        "NO_WAIT",
+        "NO_WRITE_TO_BINLOG",
+        "NTH_VALUE",
+        "NTILE",
+        "NULL",
+        "NULLS",
+        "NUMBER",
+        "NUMERIC",
+        "NVARCHAR",
+        "OF",
+        "OFF",
+        "OFFSET",
+        "OJ",
+        "OLD",
+        "OLD_PASSWORD",
+        "ON",
+        "ONE",
+        "ONLY",
+        "OPEN",
+        "OPTIMIZE",
+        "OPTIMIZER_COSTS",
+        "OPTION",
+        "OPTIONAL",
+        "OPTIONALLY",
+        "OPTIONS",
+        "OR",
+        "ORDER",
+        "ORDINALITY",
+        "ORGANIZATION",
+        "OTHERS",
+        "OUT",
+        "OUTER",
+        "OUTFILE",
+        "OVER",
+        "OWNER",
+        "PACK_KEYS",
+        "PAGE",
+        "PARSER",
+        "PARSE_GCOL_EXPR",
+        "PARTIAL",
+        "PARTITION",
+        "PARTITIONING",
+        "PARTITIONS",
+        "PASSWORD",
+        "PASSWORD_LOCK_TIME",
+        "PATH",
+        "PERCENT_RANK",
+        "PERSIST",
+        "PERSIST_ONLY",
+        "PHASE",
+        "PLUGIN",
+        "PLUGINS",
+        "PLUGIN_DIR",
+        "POINT",
+        "POLYGON",
+        "PORT",
+        "PRECEDES",
+        "PRECEDING",
+        "PRECISION",
+        "PREPARE",
+        "PRESERVE",
+        "PREV",
+        "PRIMARY",
+        "PRIVILEGE_CHECKS_USER",
+        "PRIVILEGES",
+        "PROCEDURE",
+        "PROCESS",
+        "PROCESSLIST",
+        "PROFILE",
+        "PROFILES",
+        "PROXY",
+        "PURGE",
+        "QUARTER",
+        "QUERY",
+        "QUICK",
+        "RANDOM",
+        "RANGE",
+        "RANK",
+        "READ",
+        "READS",
+        "READ_ONLY",
+        "READ_WRITE",
+        "REAL",
+        "REBUILD",
+        "RECOVER",
+        "RECURSIVE",
+        "REDOFILE",
+        "REDO_BUFFER_SIZE",
+        "REDUNDANT",
+        "REFERENCE",
+        "REFERENCES",
+        "REGEXP",
+        "REGISTRATION",
+        "RELAY",
+        "RELAYLOG",
+        "RELAY_LOG_FILE",
+        "RELAY_LOG_POS",
+        "RELAY_THREAD",
+        "RELEASE",
+        "RELOAD",
+        "REMOVE",
+        "RENAME",
+        "REORGANIZE",
+        "REPAIR",
+        "REPEAT",
+        "REPEATABLE",
+        "REPLACE",
+        "REPLICA",
+        "REPLICAS",
+        "REPLICATE_DO_DB",
+        "REPLICATE_DO_TABLE",
+        "REPLICATE_IGNORE_DB",
+        "REPLICATE_IGNORE_TABLE",
+        "REPLICATE_REWRITE_DB",
+        "REPLICATE_WILD_DO_TABLE",
+        "REPLICATE_WILD_IGNORE_TABLE",
+        "REPLICATION",
+        "REQUIRE",
+        "REQUIRE_ROW_FORMAT",
+        "RESET",
+        "RESIGNAL",
+        "RESOURCE",
+        "RESPECT",
+        "RESTART",
+        "RESTORE",
+        "RESTRICT",
+        "RESUME",
+        "RETAIN",
+        "RETURN",
+        "RETURNED_SQLSTATE",
+        "RETURNING",
+        "RETURNS",
+        "REUSE",
+        "REVERSE",
+        "REVOKE",
+        "RIGHT",
+        "RLIKE",
+        "ROLE",
+        "ROLLBACK",
+        "ROLLUP",
+        "ROTATE",
+        "ROUTINE",
+        "ROW",
+        "ROWS",
+        "ROW_COUNT",
+        "ROW_FORMAT",
+        "ROW_NUMBER",
+        "RTREE",
+        "SAVEPOINT",
+        "SCHEDULE",
+        "SCHEMA",
+        "SCHEMAS",
+        "SCHEMA_NAME",
+        "SECOND",
+        "SECOND_MICROSECOND",
+        "SECONDARY",
+        "SECONDARY_ENGINE",
+        "SECONDARY_ENGINE_ATTRIBUTE",
+        "SECONDARY_LOAD",
+        "SECONDARY_UNLOAD",
+        "SECURITY",
+        "SELECT",
+        "SENSITIVE",
+        "SEPARATOR",
+        "SERIAL",
+        "SERIALIZABLE",
+        "SERVER",
+        "SESSION",
+        "SET",
+        "SHARE",
+        "SHOW",
+        "SHUTDOWN",
+        "SIGNAL",
+        "SIGNED",
+        "SIMPLE",
+        "SKIP",
+        "SLAVE",
+        "SLOW",
+        "SMALLINT",
+        "SNAPSHOT",
+        "SOCKET",
+        "SOME",
+        "SONAME",
+        "SOUNDS",
+        "SOURCE",
+        "SOURCE_AUTO_POSITION",
+        "SOURCE_BIND",
+        "SOURCE_COMPRESSION_ALGORITHMS",
+        "SOURCE_CONNECT_RETRY",
+        "SOURCE_DELAY",
+        "SOURCE_HEARTBEAT_PERIOD",
+        "SOURCE_HOST",
+        "SOURCE_LOG_FILE",
+        "SOURCE_LOG_POS",
+        "SOURCE_PASSWORD",
+        "SOURCE_PORT",
+        "SOURCE_PUBLIC_KEY_PATH",
+        "SOURCE_RETRY_COUNT",
+        "SOURCE_SSL",
+        "SOURCE_SSL_CA",
+        "SOURCE_SSL_CAPATH",
+        "SOURCE_SSL_CERT",
+        "SOURCE_SSL_CIPHER",
+        "SOURCE_SSL_CRL",
+        "SOURCE_SSL_CRLPATH",
+        "SOURCE_SSL_KEY",
+        "SOURCE_SSL_VERIFY_SERVER_CERT",
+        "SOURCE_TLS_CIPHERSUITES",
+        "SOURCE_TLS_VERSION",
+        "SOURCE_USER",
+        "SOURCE_ZSTD_COMPRESSION_LEVEL",
+        "SPATIAL",
+        "SPECIFIC",
+        "SQL",
+        "SQLEXCEPTION",
+        "SQLSTATE",
+        "SQLWARNING",
+        "SRID",
+        "SQL_AFTER_GTIDS",
+        "SQL_AFTER_MTS_GAPS",
+        "SQL_BEFORE_GTIDS",
+        "SQL_BIG_RESULT",
+        "SQL_BUFFER_RESULT",
+        "SQL_CACHE",
+        "SQL_CALC_FOUND_ROWS",
+        "SQL_NO_CACHE",
+        "SQL_SMALL_RESULT",
+        "SQL_THREAD",
+        "SQL_TSI_DAY",
+        "SQL_TSI_HOUR",
+        "SQL_TSI_MINUTE",
+        "SQL_TSI_MONTH",
+        "SQL_TSI_QUARTER",
+        "SQL_TSI_SECOND",
+        "SQL_TSI_WEEK",
+        "SQL_TSI_YEAR",
+        "SSL",
+        "STACKED",
+        "START",
+        "STARTING",
+        "STARTS",
+        "STATS_AUTO_RECALC",
+        "STATS_PERSISTENT",
+        "STATS_SAMPLE_PAGES",
+        "STATUS",
+        "STOP",
+        "STORAGE",
+        "STORED",
+        "STRAIGHT_JOIN",
+        "STREAM",
+        "STRING",
+        "SUBCLASS_ORIGIN",
+        "SUBJECT",
+        "SUBPARTITION",
+        "SUBPARTITIONS",
+        "SUPER",
+        "SUSPEND",
+        "SWAPS",
+        "SWITCHES",
+        "SYSTEM",
+        "TABLE",
+        "TABLES",
+        "TABLESPACE",
+        "TABLE_CHECKSUM",
+        "TABLE_NAME",
+        "TEMPORARY",
+        "TEMPTABLE",
+        "TERMINATED",
+        "TEXT",
+        "THAN",
+        "THEN",
+        "THREAD_PRIORITY",
+        "TIES",
+        "TIME",
+        "TIMESTAMP",
+        "TIMESTAMPADD",
+        "TIMESTAMPDIFF",
+        "TINYBLOB",
+        "TINYINT",
+        "TINYTEXT",
+        "TLS",
+        "TO",
+        "TRAILING",
+        "TRANSACTION",
+        "TRIGGER",
+        "TRIGGERS",
+        "TRUE",
+        "TRUNCATE",
+        "TYPE",
+        "TYPES",
+        "UNBOUNDED",
+        "UNCOMMITTED",
+        "UNDEFINED",
+        "UNDO",
+        "UNDOFILE",
+        "UNDO_BUFFER_SIZE",
+        "UNICODE",
+        "UNINSTALL",
+        "UNION",
+        "UNIQUE",
+        "UNKNOWN",
+        "UNLOCK",
+        "UNREGISTER",
+        "UNSIGNED",
+        "UNTIL",
+        "UPDATE",
+        "UPGRADE",
+        "USAGE",
+        "USE",
+        "USER",
+        "USER_RESOURCES",
+        "USE_FRM",
+        "USING",
+        "UTC_DATE",
+        "UTC_TIME",
+        "UTC_TIMESTAMP",
+        "VALIDATION",
+        "VALUE",
+        "VALUES",
+        "VARBINARY",
+        "VARCHAR",
+        "VARCHARACTER",
+        "VARIABLES",
+        "VARYING",
+        "VCPU",
+        "VIEW",
+        "VIRTUAL",
+        "VISIBLE",
+        "WAIT",
+        "WARNINGS",
+        "WEEK",
+        "WEIGHT_STRING",
+        "WHEN",
+        "WHERE",
+        "WHILE",
+        "WINDOW",
+        "WITH",
+        "WITHOUT",
+        "WORK",
+        "WRAPPER",
+        "WRITE",
+        "X509",
+        "XA",
+        "XID",
+        "XML",
+        "XOR",
+        "YEAR",
+        "YEAR_MONTH",
+        "ZEROFILL",
+        "ZONE"));
+
+    public MySqlKeyWordsHandler() {
+        super(new HashSet<>(KEY_WORDS));
+    }
+
+    public MySqlKeyWordsHandler(@NotNull List<String> keyWords) {
+        super(new HashSet<>(keyWords));
+    }
+
+    public MySqlKeyWordsHandler(@NotNull Set<String> keyWords) {
+        super(keyWords);
+    }
+
+
+    @Override
+    public @NotNull String formatStyle() {
+        return "`%s`";
+    }
+
+}

+ 155 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/PostgreSqlKeyWordsHandler.java

@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.keywords;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * postgresql关键字处理
+ * https://www.postgresql.org/docs/11/sql-keywords-appendix.html
+ *
+ * @author nieqiurong 2020/5/9.
+ * @since 3.3.2
+ */
+public class PostgreSqlKeyWordsHandler extends BaseKeyWordsHandler {
+
+    private static final List<String> KEY_WORDS = new ArrayList<>(Arrays.asList(
+        "ALL",
+        "ANALYSE",
+        "ANALYZE",
+        "AND",
+        "ANY",
+        "ARRAY",
+        "AS",
+        "ASC",
+        "ASYMMETRIC",
+        "AUTHORIZATION",
+        "BINARY",
+        "BOTH",
+        "CASE",
+        "CAST",
+        "CHECK",
+        "COLLATE",
+        "COLLATION",
+        "COLUMN",
+        "CONCURRENTLY",
+        "CONSTRAINT",
+        "CREATE",
+        "CROSS",
+        "CURRENT_CATALOG",
+        "CURRENT_DATE",
+        "CURRENT_ROLE",
+        "CURRENT_SCHEMA",
+        "CURRENT_TIME",
+        "CURRENT_TIMESTAMP",
+        "CURRENT_USER",
+        "DEFAULT",
+        "DEFERRABLE",
+        "DESC",
+        "DISTINCT",
+        "DO",
+        "ELSE",
+        "END",
+        "EXCEPT",
+        "FALSE",
+        "FETCH",
+        "FOR",
+        "FOREIGN",
+        "FREEZE",
+        "FROM",
+        "FULL",
+        "GRANT",
+        "GROUP",
+        "HAVING",
+        "ILIKE",
+        "IN",
+        "INITIALLY",
+        "INNER",
+        "INTERSECT",
+        "INTO",
+        "IS",
+        "ISNULL",
+        "JOIN",
+        "LATERAL",
+        "LEADING",
+        "LEFT",
+        "LIKE",
+        "LIMIT",
+        "LOCALTIME",
+        "LOCALTIMESTAMP",
+        "NATURAL",
+        "NOT",
+        "NOTNULL",
+        "NULL",
+        "OFFSET",
+        "ON",
+        "ONLY",
+        "OR",
+        "ORDER",
+        "OUTER",
+        "OVERLAPS",
+        "PLACING",
+        "PRIMARY",
+        "REFERENCES",
+        "RETURNING",
+        "RIGHT",
+        "SELECT",
+        "SESSION_USER",
+        "SIMILAR",
+        "SOME",
+        "SYMMETRIC",
+        "TABLE",
+        "TABLESAMPLE",
+        "THEN",
+        "TO",
+        "TRAILING",
+        "TRUE",
+        "UNION",
+        "UNIQUE",
+        "USER",
+        "USING",
+        "VARIADIC",
+        "VERBOSE",
+        "WHEN",
+        "WHERE",
+        "WINDOW",
+        "WITH"
+    ));
+
+    public PostgreSqlKeyWordsHandler() {
+        super(new HashSet<>(KEY_WORDS));
+    }
+
+    public PostgreSqlKeyWordsHandler(@NotNull List<String> keyWords) {
+        super(new HashSet<>(keyWords));
+    }
+
+    public PostgreSqlKeyWordsHandler(@NotNull Set<String> keyWords) {
+        super(keyWords);
+    }
+
+    @Override
+    public @NotNull String formatStyle() {
+        return "\"%s\"";
+    }
+
+}

+ 23 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/keywords/package-info.java

@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 数据库关键字处理
+ * 由于只是生成代码上简单使用,目前简单的实现一下。<br/>
+ * 随着数据库版本的不同,关键字会有新增或移除,建议去查询对应数据库版本文档来制订关键字集合。
+ *
+ * @author nieqiurong 2020/5/8.
+ */
+package com.baomidou.mybatisplus.generator.keywords;

+ 19 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/package-info.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+/**
+ * 代码生成器相关类
+ */
+package com.baomidou.mybatisplus.generator;

+ 104 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/AbstractDatabaseQuery.java

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.query;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.querys.DbQueryDecorator;
+import com.baomidou.mybatisplus.generator.jdbc.DatabaseMetaDataWrapper;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 数据库查询抽象类
+ *
+ * @author nieqiurong
+ * @since 3.5.3
+ */
+public abstract class AbstractDatabaseQuery implements IDatabaseQuery {
+
+    protected final Logger LOGGER = LoggerFactory.getLogger(getClass());
+
+    protected final ConfigBuilder configBuilder;
+
+    protected final DataSourceConfig dataSourceConfig;
+
+    protected final StrategyConfig strategyConfig;
+
+    protected final GlobalConfig globalConfig;
+
+    protected final DbQueryDecorator dbQuery;
+
+    protected final DatabaseMetaDataWrapper databaseMetaDataWrapper;
+
+    public AbstractDatabaseQuery(@NotNull ConfigBuilder configBuilder) {
+        this.configBuilder = configBuilder;
+        this.dataSourceConfig = configBuilder.getDataSourceConfig();
+        this.strategyConfig = configBuilder.getStrategyConfig();
+        this.dbQuery = new DbQueryDecorator(dataSourceConfig, strategyConfig);
+        this.globalConfig = configBuilder.getGlobalConfig();
+        this.databaseMetaDataWrapper = new DatabaseMetaDataWrapper(dataSourceConfig);
+    }
+
+    @NotNull
+    public ConfigBuilder getConfigBuilder() {
+        return configBuilder;
+    }
+
+    @NotNull
+    public DataSourceConfig getDataSourceConfig() {
+        return dataSourceConfig;
+    }
+
+    protected void filter(List<TableInfo> tableList, List<TableInfo> includeTableList, List<TableInfo> excludeTableList) {
+        boolean isInclude = strategyConfig.getInclude().size() > 0;
+        boolean isExclude = strategyConfig.getExclude().size() > 0;
+        if (isExclude || isInclude) {
+            Map<String, String> notExistTables = new HashSet<>(isExclude ? strategyConfig.getExclude() : strategyConfig.getInclude())
+                .stream()
+                .filter(s -> !ConfigBuilder.matcherRegTable(s))
+                .collect(Collectors.toMap(String::toLowerCase, s -> s, (o, n) -> n));
+            // 将已经存在的表移除,获取配置中数据库不存在的表
+            for (TableInfo tabInfo : tableList) {
+                if (notExistTables.isEmpty()) {
+                    break;
+                }
+                //解决可能大小写不敏感的情况导致无法移除掉
+                notExistTables.remove(tabInfo.getName().toLowerCase());
+            }
+            if (notExistTables.size() > 0) {
+                LOGGER.warn("表[{}]在数据库中不存在!!!", String.join(StringPool.COMMA, notExistTables.values()));
+            }
+            // 需要反向生成的表信息
+            if (isExclude) {
+                tableList.removeAll(excludeTableList);
+            } else {
+                tableList.clear();
+                tableList.addAll(includeTableList);
+            }
+        }
+    }
+}

+ 132 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/DefaultQuery.java

@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.query;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.builder.Entity;
+import com.baomidou.mybatisplus.generator.config.po.TableField;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import com.baomidou.mybatisplus.generator.jdbc.DatabaseMetaDataWrapper;
+import com.baomidou.mybatisplus.generator.type.ITypeConvertHandler;
+import com.baomidou.mybatisplus.generator.type.TypeRegistry;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 元数据查询数据库信息.
+ *
+ * @author nieqiurong 2022/5/11.
+ * @see ITypeConvertHandler 类型转换器(如果默认逻辑不能满足,可实现此接口重写类型转换)
+ * <p>
+ * 测试通过的数据库:H2、Mysql-5.7.37、Mysql-8.0.25、PostgreSQL-11.15、PostgreSQL-14.1、Oracle-11.2.0.1.0、DM8
+ * </p>
+ * <p>
+ * FAQ:
+ * 1.Mysql无法读取表注释: 链接增加属性 remarks=true&useInformationSchema=true 或者通过{@link DataSourceConfig.Builder#addConnectionProperty(String, String)}设置
+ * 2.Oracle无法读取注释: 增加属性remarks=true,也有些驱动版本说是增加remarksReporting=true {@link DataSourceConfig.Builder#addConnectionProperty(String, String)}
+ * </p>
+ * @since 3.5.3
+ */
+public class DefaultQuery extends AbstractDatabaseQuery {
+
+    private final TypeRegistry typeRegistry;
+
+    public DefaultQuery(@NotNull ConfigBuilder configBuilder) {
+        super(configBuilder);
+        typeRegistry = new TypeRegistry(configBuilder.getGlobalConfig());
+    }
+
+    @Override
+    public @NotNull List<TableInfo> queryTables() {
+        boolean isInclude = strategyConfig.getInclude().size() > 0;
+        boolean isExclude = strategyConfig.getExclude().size() > 0;
+        //所有的表信息
+        List<TableInfo> tableList = new ArrayList<>();
+        List<DatabaseMetaDataWrapper.Table> tables = getTables();
+        //需要反向生成或排除的表信息
+        List<TableInfo> includeTableList = new ArrayList<>();
+        List<TableInfo> excludeTableList = new ArrayList<>();
+        tables.forEach(table -> {
+            String tableName = table.getName();
+            if (StringUtils.isNotBlank(tableName)) {
+                TableInfo tableInfo = new TableInfo(this.configBuilder, tableName);
+                tableInfo.setComment(table.getRemarks());
+                if (isInclude && strategyConfig.matchIncludeTable(tableName)) {
+                    includeTableList.add(tableInfo);
+                } else if (isExclude && strategyConfig.matchExcludeTable(tableName)) {
+                    excludeTableList.add(tableInfo);
+                }
+                tableList.add(tableInfo);
+            }
+        });
+        filter(tableList, includeTableList, excludeTableList);
+        // 性能优化,只处理需执行表字段 https://github.com/baomidou/mybatis-plus/issues/219
+        tableList.forEach(this::convertTableFields);
+        return tableList;
+    }
+
+    protected List<DatabaseMetaDataWrapper.Table> getTables() {
+        // 是否跳过视图
+        boolean skipView = strategyConfig.isSkipView();
+        // 获取表过滤
+        String tableNamePattern = null;
+        if (strategyConfig.getLikeTable() != null) {
+            tableNamePattern = strategyConfig.getLikeTable().getValue();
+        }
+        return databaseMetaDataWrapper.getTables(tableNamePattern, skipView ? new String[]{"TABLE"} : new String[]{"TABLE", "VIEW"});
+    }
+
+    protected void convertTableFields(@NotNull TableInfo tableInfo) {
+        String tableName = tableInfo.getName();
+        Map<String, DatabaseMetaDataWrapper.Column> columnsInfoMap = getColumnsInfo(tableName);
+        Entity entity = strategyConfig.entity();
+        columnsInfoMap.forEach((k, columnInfo) -> {
+            String columnName = columnInfo.getName();
+            TableField field = new TableField(this.configBuilder, columnName);
+            // 处理ID
+            if (columnInfo.isPrimaryKey()) {
+                field.primaryKey(columnInfo.isAutoIncrement());
+                tableInfo.setHavePrimaryKey(true);
+                if (field.isKeyIdentityFlag() && entity.getIdType() != null) {
+                    LOGGER.warn("当前表[{}]的主键为自增主键,会导致全局主键的ID类型设置失效!", tableName);
+                }
+            }
+            field.setColumnName(columnName).setComment(columnInfo.getRemarks());
+            String propertyName = entity.getNameConvert().propertyNameConvert(field);
+            // 设置字段的元数据信息
+            TableField.MetaInfo metaInfo = new TableField.MetaInfo(columnInfo, tableInfo);
+            IColumnType columnType = typeRegistry.getColumnType(metaInfo);
+            ITypeConvertHandler typeConvertHandler = dataSourceConfig.getTypeConvertHandler();
+            if (typeConvertHandler != null) {
+                columnType = typeConvertHandler.convert(globalConfig, typeRegistry, metaInfo);
+            }
+            field.setPropertyName(propertyName, columnType);
+            field.setMetaInfo(metaInfo);
+            tableInfo.addField(field);
+        });
+        tableInfo.processTable();
+    }
+
+    protected Map<String, DatabaseMetaDataWrapper.Column> getColumnsInfo(String tableName) {
+        return databaseMetaDataWrapper.getColumnsInfo(tableName, true);
+    }
+}

+ 37 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/IDatabaseQuery.java

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.query;
+
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nieqiurong 2021/1/6.
+ * @since 3.5.0
+ */
+public interface IDatabaseQuery {
+
+    /**
+     * 获取表信息
+     *
+     * @return 表信息
+     */
+    @NotNull
+    List<TableInfo> queryTables();
+
+}

+ 137 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/query/SQLQuery.java

@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.query;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.config.IDbQuery;
+import com.baomidou.mybatisplus.generator.config.ITypeConvert;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.builder.Entity;
+import com.baomidou.mybatisplus.generator.config.po.TableField;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.querys.H2Query;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import com.baomidou.mybatisplus.generator.jdbc.DatabaseMetaDataWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import java.sql.SQLException;
+import java.util.*;
+
+/**
+ * 这是兼容以前旧版本提供的查询方式,需要每个数据库对接适配。
+ *
+ * @author nieqiurong 2021/1/6.
+ * @see IDbQuery 数据库适配
+ * @see ITypeConvert 类型适配处理
+ * @since 3.5.0
+ */
+public class SQLQuery extends AbstractDatabaseQuery {
+
+    public SQLQuery(@NotNull ConfigBuilder configBuilder) {
+        super(configBuilder);
+    }
+
+    @NotNull
+    @Override
+    public List<TableInfo> queryTables() {
+        boolean isInclude = strategyConfig.getInclude().size() > 0;
+        boolean isExclude = strategyConfig.getExclude().size() > 0;
+        //所有的表信息
+        List<TableInfo> tableList = new ArrayList<>();
+
+        //需要反向生成或排除的表信息
+        List<TableInfo> includeTableList = new ArrayList<>();
+        List<TableInfo> excludeTableList = new ArrayList<>();
+        try {
+            dbQuery.execute(dbQuery.tablesSql(), result -> {
+                String tableName = result.getStringResult(dbQuery.tableName());
+                if (StringUtils.isNotBlank(tableName)) {
+                    TableInfo tableInfo = new TableInfo(this.configBuilder, tableName);
+                    String tableComment = result.getTableComment();
+                    // 跳过视图
+                    if (!(strategyConfig.isSkipView() && tableComment.toUpperCase().contains("VIEW"))) {
+                        tableInfo.setComment(tableComment);
+                        if (isInclude && strategyConfig.matchIncludeTable(tableName)) {
+                            includeTableList.add(tableInfo);
+                        } else if (isExclude && strategyConfig.matchExcludeTable(tableName)) {
+                            excludeTableList.add(tableInfo);
+                        }
+                        tableList.add(tableInfo);
+                    }
+                }
+            });
+            filter(tableList, includeTableList, excludeTableList);
+            // 性能优化,只处理需执行表字段 https://github.com/baomidou/mybatis-plus/issues/219
+            tableList.forEach(this::convertTableFields);
+            return tableList;
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        } finally {
+            // 数据库操作完成,释放连接对象
+            dbQuery.closeConnection();
+        }
+    }
+
+    protected void convertTableFields(@NotNull TableInfo tableInfo) {
+        DbType dbType = this.dataSourceConfig.getDbType();
+        String tableName = tableInfo.getName();
+        try {
+            Map<String, DatabaseMetaDataWrapper.Column> columnsInfoMap = databaseMetaDataWrapper.getColumnsInfo(tableName, false);
+            String tableFieldsSql = dbQuery.tableFieldsSql(tableName);
+            Set<String> h2PkColumns = new HashSet<>();
+            if (DbType.H2 == dbType) {
+                dbQuery.execute(String.format(H2Query.PK_QUERY_SQL, tableName), result -> {
+                    String primaryKey = result.getStringResult(dbQuery.fieldKey());
+                    if (Boolean.parseBoolean(primaryKey)) {
+                        h2PkColumns.add(result.getStringResult(dbQuery.fieldName()));
+                    }
+                });
+            }
+            Entity entity = strategyConfig.entity();
+            dbQuery.execute(tableFieldsSql, result -> {
+                String columnName = result.getStringResult(dbQuery.fieldName());
+                TableField field = new TableField(this.configBuilder, columnName);
+                DatabaseMetaDataWrapper.Column columnInfo = columnsInfoMap.get(columnName.toLowerCase());
+                // 设置字段的元数据信息
+                TableField.MetaInfo metaInfo = new TableField.MetaInfo(columnInfo, tableInfo);
+                // 避免多重主键设置,目前只取第一个找到ID,并放到list中的索引为0的位置
+                boolean isId = DbType.H2 == dbType ? h2PkColumns.contains(columnName) : result.isPrimaryKey();
+                // 处理ID
+                if (isId) {
+                    field.primaryKey(dbQuery.isKeyIdentity(result.getResultSet()));
+                    tableInfo.setHavePrimaryKey(true);
+                    if (field.isKeyIdentityFlag() && entity.getIdType() != null) {
+                        LOGGER.warn("当前表[{}]的主键为自增主键,会导致全局主键的ID类型设置失效!", tableName);
+                    }
+                }
+                // 处理ID
+                field.setColumnName(columnName)
+                    .setType(result.getStringResult(dbQuery.fieldType()))
+                    .setComment(result.getFiledComment())
+                    .setCustomMap(dbQuery.getCustomFields(result.getResultSet()));
+                String propertyName = entity.getNameConvert().propertyNameConvert(field);
+                IColumnType columnType = dataSourceConfig.getTypeConvert().processTypeConvert(globalConfig, field);
+                field.setPropertyName(propertyName, columnType);
+                field.setMetaInfo(metaInfo);
+                tableInfo.addField(field);
+            });
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+        tableInfo.processTable();
+    }
+}

+ 42 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/type/ITypeConvertHandler.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.generator.type;
+
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.po.TableField;
+import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 类型转换处理器
+ *
+ * @author nieqiurong 2022/5/12.
+ * @since 3.5.3
+ */
+public interface ITypeConvertHandler {
+
+    /**
+     * 转换字段类型
+     *
+     * @param globalConfig 全局配置
+     * @param typeRegistry 类型注册信息
+     * @param metaInfo     字段元数据信息
+     * @return 子类类型
+     */
+    @NotNull
+    IColumnType convert(GlobalConfig globalConfig, TypeRegistry typeRegistry, TableField.MetaInfo metaInfo);
+
+}

部分文件因文件數量過多而無法顯示