Browse Source

Merge remote-tracking branch 'origin/3.0' into 3.0

HouKunLin 2 years ago
parent
commit
833d649577
100 changed files with 11003 additions and 234 deletions
  1. 10 6
      build.gradle
  2. 15 6
      changelog-temp.md
  3. BIN
      libs/DmJdbcDriver-1.7.0.jar
  4. BIN
      libs/ojdbc8.jar
  5. 1 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractWrapper.java
  6. 22 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/ChainWrapper.java
  7. 7 7
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/ChainQuery.java
  8. 16 2
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/LambdaQueryChainWrapper.java
  9. 21 2
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/QueryChainWrapper.java
  10. 2 2
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/update/ChainUpdate.java
  11. 14 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/update/LambdaUpdateChainWrapper.java
  12. 14 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/update/UpdateChainWrapper.java
  13. 179 207
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java
  14. 16 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/ChainWrappers.java
  15. 554 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/Db.java
  16. 4 0
      mybatis-plus-extension/src/main/kotlin/com/baomidou/mybatisplus/extension/kotlin/KtQueryChainWrapper.kt
  17. 4 0
      mybatis-plus-extension/src/main/kotlin/com/baomidou/mybatisplus/extension/kotlin/KtUpdateChainWrapper.kt
  18. 19 0
      mybatis-plus-generator/build.gradle
  19. 221 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/AutoGenerator.java
  20. 231 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/FastAutoGenerator.java
  21. 35 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/IFill.java
  22. 34 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/ITemplate.java
  23. 90 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ConstVal.java
  24. 470 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/DataSourceConfig.java
  25. 240 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/GlobalConfig.java
  26. 11 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IConfigBuilder.java
  27. 81 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IDbQuery.java
  28. 67 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/IKeyWordsHandler.java
  29. 96 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/INameConvert.java
  30. 51 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ITypeConvert.java
  31. 196 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/InjectionConfig.java
  32. 37 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/OutputFile.java
  33. 322 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/PackageConfig.java
  34. 556 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/StrategyConfig.java
  35. 308 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateConfig.java
  36. 28 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateType.java
  37. 62 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/BaseBuilder.java
  38. 189 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/ConfigBuilder.java
  39. 216 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Controller.java
  40. 114 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/CustomFile.java
  41. 657 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Entity.java
  42. 117 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/GeneratorBuilder.java
  43. 328 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Mapper.java
  44. 110 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/PathInfoHandler.java
  45. 231 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Service.java
  46. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/package-info.java
  47. 87 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/ClickHouseTypeConvert.java
  48. 56 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DB2TypeConvert.java
  49. 82 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DmTypeConvert.java
  50. 89 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/FirebirdTypeConvert.java
  51. 89 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/KingbaseESTypeConvert.java
  52. 94 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/MySqlTypeConvert.java
  53. 96 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OracleTypeConvert.java
  54. 89 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OscarTypeConvert.java
  55. 86 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/PostgreSqlTypeConvert.java
  56. 99 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqlServerTypeConvert.java
  57. 57 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqliteTypeConvert.java
  58. 100 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/TypeConverts.java
  59. 16 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/package-info.java
  60. 49 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/Branch.java
  61. 44 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/BranchBuilder.java
  62. 95 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/select/Selector.java
  63. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/package-info.java
  64. 52 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/LikeTable.java
  65. 448 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableField.java
  66. 357 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java
  67. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/package-info.java
  68. 42 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/AbstractDbQuery.java
  69. 77 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/ClickHouseQuery.java
  70. 73 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DB2Query.java
  71. 79 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DMQuery.java
  72. 290 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DbQueryDecorator.java
  73. 56 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/DbQueryRegistry.java
  74. 95 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/FirebirdQuery.java
  75. 77 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/GaussQuery.java
  76. 110 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/GbaseQuery.java
  77. 75 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/H2Query.java
  78. 75 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/KingbaseESQuery.java
  79. 81 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/MariadbQuery.java
  80. 81 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/MySqlQuery.java
  81. 82 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/OracleQuery.java
  82. 66 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/OscarQuery.java
  83. 97 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/PostgreSqlQuery.java
  84. 97 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SqlServerQuery.java
  85. 72 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SqliteQuery.java
  86. 67 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/SybaseQuery.java
  87. 67 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/XuguQuery.java
  88. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/querys/package-info.java
  89. 38 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DateType.java
  90. 93 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbColumnType.java
  91. 39 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/IColumnType.java
  92. 142 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/NamingStrategy.java
  93. 19 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/rules/package-info.java
  94. 373 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/AbstractTemplateEngine.java
  95. 82 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/BeetlTemplateEngine.java
  96. 49 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/EnjoyTemplateEngine.java
  97. 62 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/FreemarkerTemplateEngine.java
  98. 84 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/engine/VelocityTemplateEngine.java
  99. 53 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/fill/Column.java
  100. 53 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/fill/Property.java

+ 10 - 6
build.gradle

@@ -11,11 +11,11 @@ ext {
     ]
 
     libraries = [
-        mybatisVersion = '3.5.11',
+        mybatisVersion = '3.5.10',
         mybatisSpringVersion = '2.0.7',
         mybatisSpringBootStarterVersion = '2.2.2',
-        springVersion = '6.0.2',
-        springBootVersion = '2.6.3',
+        springVersion = '5.3.15',
+        springBootVersion = '2.5.3',
         springCloudVersion = '3.1.1',
         jsqlparserVersion = '4.4', // 4.5 有bug
         junitVersion = '5.9.0',
@@ -43,7 +43,6 @@ ext {
         "javax.servlet-api"          : "javax.servlet:javax.servlet-api:4.0.1",
         "aspectjweaver"              : "org.aspectj:aspectjweaver:1.9.9.1",
         "slf4j-api"                  : "org.slf4j:slf4j-api:1.7.36",
-        "logback-classic"            : "ch.qos.logback:logback-classic:1.4.5",
         //copy
         "mybatis-spring-boot-starter": "org.mybatis.spring.boot:mybatis-spring-boot-starter:${mybatisSpringBootStarterVersion}",
         //test
@@ -68,7 +67,13 @@ 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
+        "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",
     ]
 }
 
@@ -96,7 +101,6 @@ subprojects {
         testImplementation "${lib["junit-jupiter"]}"
         testImplementation "org.mockito:mockito-junit-jupiter:4.6.1"
         testImplementation "${lib["lagarto"]}"
-        testImplementation "${lib["logback-classic"]}"
     }
 
     tasks.withType(JavaCompile) {

+ 15 - 6
changelog-temp.md

@@ -1,7 +1,16 @@
 - 多租户插件:多表join表名必需起别名,否则追加的过滤条件不带前缀
-- fix: InterceptorIgnore 不能过滤 selectKey 的问题
-- fix: 补全`mybatis-plus-boot-starter-test`遗漏配置
-- feat: 分页新增informix数据库支持
-- feat: 支持spring-boot 2.7以上版本
-- feat: 雪花id新增反解时间戳方法`Sequence#parseIdTimestamp`
-- feat: BaseMapper.selectCount生成语句加入中`AS total`
+- InterceptorIgnore 不能过滤 selectKey 的问题
+- 分页新增`informix数据库`支持
+- 分页新增`优炫数据库`支持
+- 分页新增`TDengine数据库`支持
+- 分页新增`亚马逊redshift数据库`支持
+- 支持spring-boot 2.7以上版本
+- 雪花id新增反解时间戳方法`Sequence#parseIdTimestamp`
+- BaseMapper.selectCount生成语句加入中`AS total`
+- 修复IllegalSQLInnerInterceptor类ClassCastException异常,并优化日志
+- 移除注解`OrderBy`的过时属性`isDesc`
+- 移除`TableInfo`过时方法
+- 加入`JoinTableInfoInitHandler`类参与`TableInfo`初始化
+- 修复StringUtils.sqlInjectionReplaceBlank方法过滤sql不全,可能会导致sql注入的情况
+- 增加IService.lambdaQuery(entity)支持,写法更便捷
+- 新增数据变更记录(数据审计)插件`DataChangeRecorderInnerInterceptor`

BIN
libs/DmJdbcDriver-1.7.0.jar


BIN
libs/ojdbc8.jar


+ 1 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractWrapper.java

@@ -345,8 +345,7 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
     }
 
     @Override
-    @SafeVarargs
-    public final Children orderBy(boolean condition, boolean isAsc, R column, R... columns) {
+    public Children orderBy(boolean condition, boolean isAsc, R column, R... columns) {
         return maybeDo(condition, () -> {
             final SqlKeyword mode = isAsc ? ASC : DESC;
             appendSqlSegments(ORDER_BY, columnToSqlSegment(columnSqlInjectFilter(column)), mode);

+ 22 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/ChainWrapper.java

@@ -15,8 +15,12 @@
  */
 package com.baomidou.mybatisplus.extension.conditions;
 
+import java.util.Optional;
+
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 
 /**
  * 此接口没特殊意义,只是为了减少实现类的代码量,主要在 AbstractChainWrapper 抽象类上实现
@@ -40,4 +44,22 @@ public interface ChainWrapper<T> {
      * @return Wrapper
      */
     Wrapper<T> getWrapper();
+
+    /**
+     * 获取当前实体Class
+     *
+     * @return Class
+     */
+    Class<T> getEntityClass();
+
+    /**
+     * 执行baseMapper操作,有baseMapper操作时使用baseMapper,没有时通过entityClass获取baseMapper,再使用
+     *
+     * @param function 操作
+     * @param <R>      返回值
+     * @return 结果
+     */
+    default <R> R execute(SFunction<BaseMapper<T>, R> function) {
+        return Optional.ofNullable(getBaseMapper()).map(function).orElseGet(() -> SqlHelper.execute(getEntityClass(), function));
+    }
 }

+ 7 - 7
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/ChainQuery.java

@@ -15,13 +15,13 @@
  */
 package com.baomidou.mybatisplus.extension.conditions.query;
 
+import java.util.List;
+import java.util.Optional;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.conditions.ChainWrapper;
 import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 
-import java.util.List;
-import java.util.Optional;
-
 /**
  * 具有查询方法的定义
  *
@@ -36,7 +36,7 @@ public interface ChainQuery<T> extends ChainWrapper<T> {
      * @return 集合
      */
     default List<T> list() {
-        return getBaseMapper().selectList(getWrapper());
+        return execute(mapper -> mapper.selectList(getWrapper()));
     }
 
     /**
@@ -45,7 +45,7 @@ public interface ChainQuery<T> extends ChainWrapper<T> {
      * @return 单个
      */
     default T one() {
-        return getBaseMapper().selectOne(getWrapper());
+        return execute(mapper -> mapper.selectOne(getWrapper()));
     }
 
     /**
@@ -64,7 +64,7 @@ public interface ChainQuery<T> extends ChainWrapper<T> {
      * @return count
      */
     default Long count() {
-        return SqlHelper.retCount(getBaseMapper().selectCount(getWrapper()));
+        return execute(mapper -> SqlHelper.retCount(mapper.selectCount(getWrapper())));
     }
 
     /**
@@ -83,6 +83,6 @@ public interface ChainQuery<T> extends ChainWrapper<T> {
      * @return 分页数据
      */
     default <E extends IPage<T>> E page(E page) {
-        return getBaseMapper().selectPage(page, getWrapper());
+        return execute(mapper -> mapper.selectPage(page, getWrapper()));
     }
 }

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

@@ -15,6 +15,8 @@
  */
 package com.baomidou.mybatisplus.extension.conditions.query;
 
+import java.util.function.Predicate;
+
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.Query;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -23,8 +25,6 @@ import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.baomidou.mybatisplus.extension.conditions.AbstractChainWrapper;
 
-import java.util.function.Predicate;
-
 /**
  * @author miemie
  * @since 2018-12-19
@@ -34,10 +34,19 @@ public class LambdaQueryChainWrapper<T> extends AbstractChainWrapper<T, SFunctio
     implements ChainQuery<T>, Query<LambdaQueryChainWrapper<T>, T, SFunction<T, ?>> {
 
     private final BaseMapper<T> baseMapper;
+    private Class<T> entityClass;
 
     public LambdaQueryChainWrapper(BaseMapper<T> baseMapper) {
         super();
         this.baseMapper = baseMapper;
+        this.entityClass = null;
+        super.wrapperChildren = new LambdaQueryWrapper<>();
+    }
+
+    public LambdaQueryChainWrapper(Class<T> entityClass) {
+        super();
+        this.baseMapper = null;
+        this.entityClass = entityClass;
         super.wrapperChildren = new LambdaQueryWrapper<>();
     }
 
@@ -75,4 +84,9 @@ public class LambdaQueryChainWrapper<T> extends AbstractChainWrapper<T, SFunctio
     public BaseMapper<T> getBaseMapper() {
         return baseMapper;
     }
+
+    @Override
+    public Class<T> getEntityClass() {
+        return entityClass;
+    }
 }

+ 21 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/query/QueryChainWrapper.java

@@ -15,6 +15,8 @@
  */
 package com.baomidou.mybatisplus.extension.conditions.query;
 
+import java.util.function.Predicate;
+
 import com.baomidou.mybatisplus.core.conditions.query.Query;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -22,8 +24,6 @@ import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.extension.conditions.AbstractChainWrapper;
 
-import java.util.function.Predicate;
-
 /**
  * Query Chain Wrapper
  *
@@ -35,10 +35,19 @@ public class QueryChainWrapper<T> extends AbstractChainWrapper<T, String, QueryC
     implements ChainQuery<T>, Query<QueryChainWrapper<T>, T, String> {
 
     private final BaseMapper<T> baseMapper;
+    private final Class<T> entityClass;
 
     public QueryChainWrapper(BaseMapper<T> baseMapper) {
         super();
         this.baseMapper = baseMapper;
+        this.entityClass = null;
+        super.wrapperChildren = new QueryWrapper<>();
+    }
+
+    public QueryChainWrapper(Class<T> entityClass) {
+        super();
+        this.baseMapper = null;
+        this.entityClass = entityClass;
         super.wrapperChildren = new QueryWrapper<>();
     }
 
@@ -63,4 +72,14 @@ public class QueryChainWrapper<T> extends AbstractChainWrapper<T, String, QueryC
     public BaseMapper<T> getBaseMapper() {
         return baseMapper;
     }
+
+    /**
+     * 获取当前实体Class
+     *
+     * @return Class
+     */
+    @Override
+    public Class<T> getEntityClass() {
+        return entityClass;
+    }
 }

+ 2 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/update/ChainUpdate.java

@@ -42,7 +42,7 @@ public interface ChainUpdate<T> extends ChainWrapper<T> {
      * @return 是否成功
      */
     default boolean update(T entity) {
-        return SqlHelper.retBool(getBaseMapper().update(entity, getWrapper()));
+        return execute(mapper -> SqlHelper.retBool(mapper.update(entity, getWrapper())));
     }
 
     /**
@@ -51,6 +51,6 @@ public interface ChainUpdate<T> extends ChainWrapper<T> {
      * @return 是否成功
      */
     default boolean remove() {
-        return SqlHelper.retBool(getBaseMapper().delete(getWrapper()));
+        return execute(mapper -> SqlHelper.retBool(mapper.delete(getWrapper())));
     }
 }

+ 14 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/update/LambdaUpdateChainWrapper.java

@@ -33,10 +33,19 @@ public class LambdaUpdateChainWrapper<T> extends AbstractChainWrapper<T, SFuncti
     implements ChainUpdate<T>, Update<LambdaUpdateChainWrapper<T>, SFunction<T, ?>> {
 
     private final BaseMapper<T> baseMapper;
+    private final Class<T> entityClass;
 
     public LambdaUpdateChainWrapper(BaseMapper<T> baseMapper) {
         super();
         this.baseMapper = baseMapper;
+        this.entityClass = null;
+        super.wrapperChildren = new LambdaUpdateWrapper<>();
+    }
+
+    public LambdaUpdateChainWrapper(Class<T> entityClass) {
+        super();
+        this.baseMapper = null;
+        this.entityClass = entityClass;
         super.wrapperChildren = new LambdaUpdateWrapper<>();
     }
 
@@ -61,4 +70,9 @@ public class LambdaUpdateChainWrapper<T> extends AbstractChainWrapper<T, SFuncti
     public BaseMapper<T> getBaseMapper() {
         return baseMapper;
     }
+
+    @Override
+    public Class<T> getEntityClass() {
+        return entityClass;
+    }
 }

+ 14 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/update/UpdateChainWrapper.java

@@ -32,10 +32,19 @@ public class UpdateChainWrapper<T> extends AbstractChainWrapper<T, String, Updat
     implements ChainUpdate<T>, Update<UpdateChainWrapper<T>, String> {
 
     private final BaseMapper<T> baseMapper;
+    private final Class<T> entityClass;
 
     public UpdateChainWrapper(BaseMapper<T> baseMapper) {
         super();
         this.baseMapper = baseMapper;
+        this.entityClass = null;
+        super.wrapperChildren = new UpdateWrapper<>();
+    }
+
+    public UpdateChainWrapper(Class<T> entityClass) {
+        super();
+        this.baseMapper = null;
+        this.entityClass = entityClass;
         super.wrapperChildren = new UpdateWrapper<>();
     }
 
@@ -60,4 +69,9 @@ public class UpdateChainWrapper<T> extends AbstractChainWrapper<T, String, Updat
     public BaseMapper<T> getBaseMapper() {
         return baseMapper;
     }
+
+    @Override
+    public Class<T> getEntityClass() {
+        return entityClass;
+    }
 }

+ 179 - 207
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInterceptor.java → mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java

@@ -1,45 +1,8 @@
 package com.baomidou.mybatisplus.extension.plugins.inner;
 
-import static com.baomidou.mybatisplus.extension.plugins.inner.DataChangeRecorderInterceptor.convertDoubleQuotes;
-
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.ParameterMapping;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.plugin.Intercepts;
-import org.apache.ibatis.plugin.Signature;
-import org.apache.ibatis.reflection.MetaObject;
-import org.apache.ibatis.reflection.SystemMetaObject;
-import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-
 import lombok.Data;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.JdbcParameter;
@@ -49,13 +12,26 @@ import net.sf.jsqlparser.schema.Table;
 import net.sf.jsqlparser.statement.Statement;
 import net.sf.jsqlparser.statement.delete.Delete;
 import net.sf.jsqlparser.statement.insert.Insert;
-import net.sf.jsqlparser.statement.select.AllColumns;
-import net.sf.jsqlparser.statement.select.PlainSelect;
-import net.sf.jsqlparser.statement.select.Select;
-import net.sf.jsqlparser.statement.select.SelectExpressionItem;
-import net.sf.jsqlparser.statement.select.SelectItem;
+import net.sf.jsqlparser.statement.select.*;
 import net.sf.jsqlparser.statement.update.Update;
 import net.sf.jsqlparser.statement.update.UpdateSet;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.sql.*;
+import java.util.Date;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * <p>
@@ -63,51 +39,46 @@ import net.sf.jsqlparser.statement.update.UpdateSet;
  * 默认会生成一条log,格式:
  * ----------------------INSERT LOG------------------------------
  * {
- *   "tableName": "h2user",
- *   "operation": "insert",
- *   "recordStatus": "true",
- *   "changedData": [
- *     {
- *       "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512",
- *       "TEST_ID": "null->1561666810058739714",
- *       "AGE": "null->THREE"
- *     }
- *   ],
- *   "cost(ms)": 0
+ * "tableName": "h2user",
+ * "operation": "insert",
+ * "recordStatus": "true",
+ * "changedData": [
+ * {
+ * "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512",
+ * "TEST_ID": "null->1561666810058739714",
+ * "AGE": "null->THREE"
+ * }
+ * ],
+ * "cost(ms)": 0
  * }
  * </p>
  * <p>
- *  * ----------------------UPDATE LOG------------------------------
- *
+ * * ----------------------UPDATE LOG------------------------------
+ * <p>
  * {
- *   "tableName": "h2user",
- *   "operation": "update",
- *   "recordStatus": "true",
- *   "changedData": [
- *     {
- *       "TEST_ID": "102",
- *       "AGE": "2->THREE",
- *       "FIRSTNAME": "DOU.HAO->{\"json\":\"abc\"}",
- *       "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512"
- *     }
- *   ],
- *   "cost(ms)": 0
+ * "tableName": "h2user",
+ * "operation": "update",
+ * "recordStatus": "true",
+ * "changedData": [
+ * {
+ * "TEST_ID": "102",
+ * "AGE": "2->THREE",
+ * "FIRSTNAME": "DOU.HAO->{\"json\":\"abc\"}",
+ * "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512"
+ * }
+ * ],
+ * "cost(ms)": 0
  * }
  * </p>
  *
  * @author yuxiaobin
  * @date 2022-8-21
  */
-@Intercepts({
-    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
-})
-public class DataChangeRecorderInterceptor implements InnerInterceptor {
-
+public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
     @SuppressWarnings("unused")
     public static final String IGNORED_TABLE_COLUMN_PROPERTIES = "ignoredTableColumns";
 
-    private final Logger logger = LoggerFactory.getLogger("DataChangeRecorder");
-
     private final Map<String, Set<String>> ignoredTableColumns = new ConcurrentHashMap<>();
     private final Set<String> ignoreAllColumns = new HashSet<>();//全部表的这些字段名,INSERT/UPDATE都忽略,delete暂时保留
 
@@ -515,13 +486,6 @@ public class DataChangeRecorderInterceptor implements InnerInterceptor {
         }
     }
 
-    public static String convertDoubleQuotes(Object obj) {
-        if (obj == null) {
-            return null;
-        }
-        return obj.toString().replace("\"", "\\\"");
-    }
-
     @Data
     public static class OperationResult {
 
@@ -585,160 +549,168 @@ public class DataChangeRecorderInterceptor implements InnerInterceptor {
             sb.append("}");
             return sb.toString();
         }
-
     }
 
-}
-
-
-@Data
-class Columns2SelectItemsResult {
+    @Data
+    public static class Columns2SelectItemsResult {
 
-    private Column pk;
-    /**
-     * all column with additional columns: ID, etc.
-     */
-    private List<SelectItem> selectItems;
-    /**
-     * newly added column count from meta data.
-     */
-    private int additionalItemCount;
+        private Column pk;
+        /**
+         * all column with additional columns: ID, etc.
+         */
+        private List<SelectItem> selectItems;
+        /**
+         * newly added column count from meta data.
+         */
+        private int additionalItemCount;
 
-    public static Columns2SelectItemsResult build(List<SelectItem> selectItems, int additionalItemCount) {
-        Columns2SelectItemsResult result = new Columns2SelectItemsResult();
-        result.setSelectItems(selectItems);
-        result.setAdditionalItemCount(additionalItemCount);
-        return result;
+        public static Columns2SelectItemsResult build(List<SelectItem> selectItems, int additionalItemCount) {
+            Columns2SelectItemsResult result = new Columns2SelectItemsResult();
+            result.setSelectItems(selectItems);
+            result.setAdditionalItemCount(additionalItemCount);
+            return result;
+        }
     }
 
-}
+    @Data
+    public static class OriginalDataObj {
 
-@Data
-class OriginalDataObj {
+        private List<DataChangedRecord> originalDataObj;
 
-    private List<DataChangedRecord> originalDataObj;
+        public boolean isEmpty() {
+            return originalDataObj == null || originalDataObj.isEmpty();
+        }
 
-    public boolean isEmpty() {
-        return originalDataObj == null || originalDataObj.isEmpty();
     }
 
-}
-
-@Data
-class DataColumnChangeResult {
-
-    private String columnName;
-    private Object originalValue;
-    private Object updateValue;
-
-    @SuppressWarnings("rawtypes")
-    public boolean isDataChanged(Object updateValue) {
-        if (!Objects.equals(originalValue, updateValue)) {
-            if (updateValue instanceof Number && originalValue instanceof Number) {
-                BigDecimal update = new BigDecimal(updateValue.toString());
-                BigDecimal original = new BigDecimal(originalValue.toString());
-                return update.compareTo(original) != 0;
-            }
-            if (updateValue instanceof Date && originalValue instanceof Date) {
-                Date update = (Date) updateValue;
-                Date original = (Date) originalValue;
-                return update.compareTo(original) != 0;
+    @Data
+    public static class DataColumnChangeResult {
+
+        private String columnName;
+        private Object originalValue;
+        private Object updateValue;
+
+        @SuppressWarnings("rawtypes")
+        public boolean isDataChanged(Object updateValue) {
+            if (!Objects.equals(originalValue, updateValue)) {
+                if (updateValue instanceof Number && originalValue instanceof Number) {
+                    BigDecimal update = new BigDecimal(updateValue.toString());
+                    BigDecimal original = new BigDecimal(originalValue.toString());
+                    return update.compareTo(original) != 0;
+                }
+                if (updateValue instanceof Date && originalValue instanceof Date) {
+                    Date update = (Date) updateValue;
+                    Date original = (Date) originalValue;
+                    return update.compareTo(original) != 0;
+                }
+                if (originalValue instanceof Clob) {
+                    String originalStr = convertClob((Clob) originalValue);
+                    setOriginalValue(originalStr);
+                    return !originalStr.equals(updateValue);
+                }
+                return true;
             }
-            if (originalValue instanceof Clob) {
-                String originalStr = convertClob((Clob) originalValue);
-                setOriginalValue(originalStr);
-                return !originalStr.equals(updateValue);
+            if (originalValue instanceof Comparable) {
+                Comparable original = (Comparable) originalValue;
+                Comparable update = (Comparable) updateValue;
+                return original.compareTo(update) != 0;
             }
-            return true;
+            return false;
         }
-        if (originalValue instanceof Comparable) {
-            Comparable original = (Comparable) originalValue;
-            Comparable update = (Comparable) updateValue;
-            return original.compareTo(update) != 0;
-        }
-        return false;
-    }
 
-    public static String convertClob(Clob clobObj) {
-        try {
-            return clobObj.getSubString(0, (int) clobObj.length());
-        } catch (Exception e) {
-            try (Reader is = clobObj.getCharacterStream()) {
-                char[] chars = new char[64];
-                int readChars;
-                StringBuilder sb = new StringBuilder();
-                while ((readChars = is.read(chars)) != -1) {
-                    sb.append(chars, 0, readChars);
+        public static String convertClob(Clob clobObj) {
+            try {
+                return clobObj.getSubString(0, (int) clobObj.length());
+            } catch (Exception e) {
+                try (Reader is = clobObj.getCharacterStream()) {
+                    char[] chars = new char[64];
+                    int readChars;
+                    StringBuilder sb = new StringBuilder();
+                    while ((readChars = is.read(chars)) != -1) {
+                        sb.append(chars, 0, readChars);
+                    }
+                    return sb.toString();
+                } catch (Exception e2) {
+                    //ignored
+                    return "unknown clobObj";
                 }
-                return sb.toString();
-            } catch (Exception e2) {
-                //ignored
-                return "unknown clobObj";
             }
         }
-    }
 
-    public static DataColumnChangeResult constrcutByUpdateVal(String columnName, Object updateValue) {
-        DataColumnChangeResult res = new DataColumnChangeResult();
-        res.setColumnName(columnName);
-        res.setUpdateValue(updateValue);
-        return res;
-    }
+        public static DataColumnChangeResult constrcutByUpdateVal(String columnName, Object updateValue) {
+            DataColumnChangeResult res = new DataColumnChangeResult();
+            res.setColumnName(columnName);
+            res.setUpdateValue(updateValue);
+            return res;
+        }
 
-    public static DataColumnChangeResult constrcutByOriginalVal(String columnName, Object originalValue) {
-        DataColumnChangeResult res = new DataColumnChangeResult();
-        res.setColumnName(columnName);
-        res.setOriginalValue(originalValue);
-        return res;
-    }
+        public static DataColumnChangeResult constrcutByOriginalVal(String columnName, Object originalValue) {
+            DataColumnChangeResult res = new DataColumnChangeResult();
+            res.setColumnName(columnName);
+            res.setOriginalValue(originalValue);
+            return res;
+        }
 
-    public String generateDataStr() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("\"").append(columnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(originalValue)).append("->").append(convertDoubleQuotes(updateValue)).append("\"").append(",");
-        return sb.toString();
+        public String generateDataStr() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("\"").append(columnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(originalValue)).append("->").append(convertDoubleQuotes(updateValue)).append("\"").append(",");
+            return sb.toString();
+        }
+
+        public String convertDoubleQuotes(Object obj) {
+            if (obj == null) {
+                return null;
+            }
+            return obj.toString().replace("\"", "\\\"");
+        }
     }
-}
 
-@Data
-class DataChangedRecord {
-    private String pkColumnName;
-    private Object pkColumnVal;
-    private List<DataColumnChangeResult> originalColumnDatas;
-    private List<DataColumnChangeResult> updatedColumns;
-
-    public boolean hasUpdate(Map<String, Object> columnNameValMap, Set<String> ignoredColumns, Set<String> ignoreAllColumns) {
-        if (originalColumnDatas == null) {
-            return true;
-        }
-        boolean hasUpdate = false;
-        updatedColumns = new ArrayList<>(originalColumnDatas.size());
-        for (DataColumnChangeResult originalColumn : originalColumnDatas) {
-            final String columnName = originalColumn.getColumnName().toUpperCase();
-            if (ignoredColumns != null && ignoredColumns.contains(columnName) || ignoreAllColumns.contains(columnName)) {
-                continue;
+    @Data
+    public static class DataChangedRecord {
+        private String pkColumnName;
+        private Object pkColumnVal;
+        private List<DataColumnChangeResult> originalColumnDatas;
+        private List<DataColumnChangeResult> updatedColumns;
+
+        public boolean hasUpdate(Map<String, Object> columnNameValMap, Set<String> ignoredColumns, Set<String> ignoreAllColumns) {
+            if (originalColumnDatas == null) {
+                return true;
             }
-            Object updatedValue = columnNameValMap.get(columnName);
-            if (originalColumn.isDataChanged(updatedValue)) {
-                hasUpdate = true;
-                originalColumn.setUpdateValue(updatedValue);
-                updatedColumns.add(originalColumn);
+            boolean hasUpdate = false;
+            updatedColumns = new ArrayList<>(originalColumnDatas.size());
+            for (DataColumnChangeResult originalColumn : originalColumnDatas) {
+                final String columnName = originalColumn.getColumnName().toUpperCase();
+                if (ignoredColumns != null && ignoredColumns.contains(columnName) || ignoreAllColumns.contains(columnName)) {
+                    continue;
+                }
+                Object updatedValue = columnNameValMap.get(columnName);
+                if (originalColumn.isDataChanged(updatedValue)) {
+                    hasUpdate = true;
+                    originalColumn.setUpdateValue(updatedValue);
+                    updatedColumns.add(originalColumn);
+                }
             }
+            return hasUpdate;
         }
-        return hasUpdate;
-    }
 
-    public String generateUpdatedDataStr() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("{");
-        if (pkColumnName != null) {
-            sb.append("\"").append(pkColumnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(pkColumnVal)).append("\"").append(",");
+        public String generateUpdatedDataStr() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("{");
+            if (pkColumnName != null) {
+                sb.append("\"").append(pkColumnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(pkColumnVal)).append("\"").append(",");
+            }
+            for (DataColumnChangeResult update : updatedColumns) {
+                sb.append(update.generateDataStr());
+            }
+            sb.replace(sb.length() - 1, sb.length(), "}");
+            return sb.toString();
         }
-        for (DataColumnChangeResult update : updatedColumns) {
-            sb.append(update.generateDataStr());
+
+        public String convertDoubleQuotes(Object obj) {
+            if (obj == null) {
+                return null;
+            }
+            return obj.toString().replace("\"", "\\\"");
         }
-        sb.replace(sb.length() - 1, sb.length(), "}");
-        return sb.toString();
     }
-
-
 }

+ 16 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/ChainWrappers.java

@@ -45,6 +45,10 @@ public final class ChainWrappers {
         return new QueryChainWrapper<>(mapper);
     }
 
+    public static <T> QueryChainWrapper<T> queryChain(Class<T> entityClass) {
+        return new QueryChainWrapper<>(entityClass);
+    }
+
     /**
      * 链式查询 lambda 式
      * <p>注意:不支持 Kotlin </p>
@@ -55,6 +59,10 @@ public final class ChainWrappers {
         return new LambdaQueryChainWrapper<>(mapper);
     }
 
+    public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(Class<T> entityClass) {
+        return new LambdaQueryChainWrapper<>(entityClass);
+    }
+
     /**
      * 链式查询 lambda 式
      * <p>注意:不支持 Kotlin </p>
@@ -104,6 +112,10 @@ public final class ChainWrappers {
         return new UpdateChainWrapper<>(mapper);
     }
 
+    public static <T> UpdateChainWrapper<T> updateChain(Class<T> entityClass) {
+        return new UpdateChainWrapper<>(entityClass);
+    }
+
     /**
      * 链式更改 lambda 式
      * <p>注意:不支持 Kotlin </p>
@@ -114,6 +126,10 @@ public final class ChainWrappers {
         return new LambdaUpdateChainWrapper<>(mapper);
     }
 
+    public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(Class<T> entityClass) {
+        return new LambdaUpdateChainWrapper<>(entityClass);
+    }
+
     /**
      * 链式更改 lambda 式
      * 仅支持 Kotlin

+ 554 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/Db.java

@@ -0,0 +1,554 @@
+package com.baomidou.mybatisplus.extension.toolkit;
+
+import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.*;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
+import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
+import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
+import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.apache.ibatis.binding.MapperMethod;
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 以静态方式调用Service中的函数
+ *
+ * @author VampireAchao
+ * @since 2022-05-03
+ */
+public class Db {
+
+    private static final Log log = LogFactory.getLog(Db.class);
+
+    private Db() {
+        /* Do not new me! */
+    }
+
+    /**
+     * 插入一条记录(选择字段,策略插入)
+     *
+     * @param entity 实体对象
+     */
+    public static <T> boolean save(T entity) {
+        if (Objects.isNull(entity)) {
+            return false;
+        }
+        @SuppressWarnings("unchecked")
+        Class<T> entityClass = (Class<T>) entity.getClass();
+        Integer result = SqlHelper.execute(entityClass, baseMapper -> baseMapper.insert(entity));
+        return SqlHelper.retBool(result);
+    }
+
+    /**
+     * 插入(批量)
+     *
+     * @param entityList 实体对象集合
+     */
+    public static <T> boolean saveBatch(Collection<T> entityList) {
+        return saveBatch(entityList, IService.DEFAULT_BATCH_SIZE);
+    }
+
+    /**
+     * 插入(批量)
+     *
+     * @param entityList 实体对象集合
+     * @param batchSize  插入批次数量
+     */
+    public static <T> boolean saveBatch(Collection<T> entityList, int batchSize) {
+        if (CollectionUtils.isEmpty(entityList)) {
+            return false;
+        }
+        Class<T> entityClass = getEntityClass(entityList);
+        Class<?> mapperClass = ClassUtils.toClassConfident(getTableInfo(entityClass).getCurrentNamespace());
+        String sqlStatement = SqlHelper.getSqlStatement(mapperClass, SqlMethod.INSERT_ONE);
+        return SqlHelper.executeBatch(entityClass, LogFactory.getLog(Db.class), entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
+    }
+
+    /**
+     * 批量修改插入
+     *
+     * @param entityList 实体对象集合
+     */
+    public static <T> boolean saveOrUpdateBatch(Collection<T> entityList) {
+        return saveOrUpdateBatch(entityList, IService.DEFAULT_BATCH_SIZE);
+    }
+
+    /**
+     * 批量修改插入
+     *
+     * @param entityList 实体对象集合
+     * @param batchSize  每次的数量
+     */
+    public static <T> boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
+        if (CollectionUtils.isEmpty(entityList)) {
+            return false;
+        }
+        Class<T> entityClass = getEntityClass(entityList);
+        TableInfo tableInfo = getTableInfo(entityClass);
+        Class<?> mapperClass = ClassUtils.toClassConfident(tableInfo.getCurrentNamespace());
+        String keyProperty = tableInfo.getKeyProperty();
+        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for primary key from entity!");
+        return SqlHelper.saveOrUpdateBatch(entityClass, mapperClass, LogFactory.getLog(Db.class), entityList, batchSize, (sqlSession, entity) -> {
+            Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
+            return StringUtils.checkValNull(idVal)
+                || CollectionUtils.isEmpty(sqlSession.selectList(SqlHelper.getSqlStatement(mapperClass, SqlMethod.SELECT_BY_ID), entity));
+        }, (sqlSession, entity) -> {
+            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
+            param.put(Constants.ENTITY, entity);
+            sqlSession.update(SqlHelper.getSqlStatement(mapperClass, SqlMethod.UPDATE_BY_ID), param);
+        });
+    }
+
+    /**
+     * 根据 ID 删除
+     *
+     * @param id          主键ID
+     * @param entityClass 实体类
+     */
+    public static <T> boolean removeById(Serializable id, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> SqlHelper.retBool(baseMapper.deleteById(id)));
+    }
+
+    /**
+     * 根据实体(ID)删除
+     *
+     * @param entity 实体
+     */
+    public static <T> boolean removeById(T entity) {
+        if (Objects.isNull(entity)) {
+            return false;
+        }
+        @SuppressWarnings("unchecked")
+        Class<T> entityClass = (Class<T>) entity.getClass();
+        return SqlHelper.execute(entityClass, baseMapper -> SqlHelper.retBool(baseMapper.deleteById(entity)));
+    }
+
+    /**
+     * 根据 entity 条件,删除记录
+     *
+     * @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> boolean remove(AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> SqlHelper.retBool(baseMapper.delete(queryWrapper)));
+    }
+
+    /**
+     * 根据 ID 选择修改
+     *
+     * @param entity 实体对象
+     */
+    public static <T> boolean updateById(T entity) {
+        if (Objects.isNull(entity)) {
+            return false;
+        }
+        @SuppressWarnings("unchecked")
+        Class<T> entityClass = (Class<T>) entity.getClass();
+        return SqlHelper.execute(entityClass, baseMapper -> SqlHelper.retBool(baseMapper.updateById(entity)));
+    }
+
+    /**
+     * 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
+     *
+     * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
+     */
+    public static <T> boolean update(AbstractWrapper<T, ?, ?> updateWrapper) {
+        return update(null, updateWrapper);
+    }
+
+    /**
+     * 根据 whereEntity 条件,更新记录
+     *
+     * @param entity        实体对象
+     * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
+     */
+    public static <T> boolean update(T entity, AbstractWrapper<T, ?, ?> updateWrapper) {
+        return SqlHelper.execute(getEntityClass(updateWrapper), baseMapper -> SqlHelper.retBool(baseMapper.update(entity, updateWrapper)));
+    }
+
+    /**
+     * 根据ID 批量更新
+     *
+     * @param entityList 实体对象集合
+     */
+    public static <T> boolean updateBatchById(Collection<T> entityList) {
+        return updateBatchById(entityList, IService.DEFAULT_BATCH_SIZE);
+    }
+
+    /**
+     * 根据ID 批量更新
+     *
+     * @param entityList 实体对象集合
+     * @param batchSize  更新批次数量
+     */
+    public static <T> boolean updateBatchById(Collection<T> entityList, int batchSize) {
+        Class<T> entityClass = getEntityClass(entityList);
+        TableInfo tableInfo = getTableInfo(entityClass);
+        String sqlStatement = SqlHelper.getSqlStatement(ClassUtils.toClassConfident(tableInfo.getCurrentNamespace()), SqlMethod.UPDATE_BY_ID);
+        return SqlHelper.executeBatch(entityClass, LogFactory.getLog(Db.class), entityList, batchSize, (sqlSession, entity) -> {
+            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
+            param.put(Constants.ENTITY, entity);
+            sqlSession.update(sqlStatement, param);
+        });
+    }
+
+    /**
+     * 删除(根据ID 批量删除)
+     *
+     * @param list        主键ID或实体列表
+     * @param entityClass 实体类
+     */
+    public static <T> boolean removeByIds(Collection<? extends Serializable> list, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> SqlHelper.retBool(baseMapper.deleteBatchIds(list)));
+    }
+
+    /**
+     * 根据 columnMap 条件,删除记录
+     *
+     * @param columnMap   表字段 map 对象
+     * @param entityClass 实体类
+     */
+    public static <T> boolean removeByMap(Map<String, Object> columnMap, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> SqlHelper.retBool(baseMapper.deleteByMap(columnMap)));
+    }
+
+    /**
+     * TableId 注解存在更新记录,否插入一条记录
+     *
+     * @param entity 实体对象
+     */
+    public static <T> boolean saveOrUpdate(T entity) {
+        if (Objects.isNull(entity)) {
+            return false;
+        }
+        @SuppressWarnings("unchecked")
+        Class<T> entityClass = (Class<T>) entity.getClass();
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
+        Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
+        String keyProperty = tableInfo.getKeyProperty();
+        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
+        Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
+        return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal, entityClass)) ? save(entity) : updateById(entity);
+    }
+
+    /**
+     * 根据 ID 查询
+     *
+     * @param id          主键ID
+     * @param entityClass 实体类
+     */
+    public static <T> T getById(Serializable id, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectById(id));
+    }
+
+    /**
+     * 根据 Wrapper,查询一条记录 <br/>
+     * <p>结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> T getOne(AbstractWrapper<T, ?, ?> queryWrapper) {
+        return getOne(queryWrapper, true);
+    }
+
+    /**
+     * 根据 Wrapper,查询一条记录
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     * @param throwEx      有多个 result 是否抛出异常
+     */
+    public static <T> T getOne(AbstractWrapper<T, ?, ?> queryWrapper, boolean throwEx) {
+        Class<T> entityClass = getEntityClass(queryWrapper);
+        if (throwEx) {
+            return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectOne(queryWrapper));
+        }
+        return SqlHelper.execute(entityClass, baseMapper -> SqlHelper.getObject(log, baseMapper.selectList(queryWrapper)));
+    }
+
+    /**
+     * 查询(根据 columnMap 条件)
+     *
+     * @param columnMap   表字段 map 对象
+     * @param entityClass 实体类
+     */
+    public static <T> List<T> listByMap(Map<String, Object> columnMap, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectByMap(columnMap));
+    }
+
+    /**
+     * 查询(根据ID 批量查询)
+     *
+     * @param idList      主键ID列表
+     * @param entityClass 实体类
+     */
+    public static <T> List<T> listByIds(Collection<? extends Serializable> idList, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectBatchIds(idList));
+    }
+
+    /**
+     * 根据 Wrapper,查询一条记录
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> Map<String, Object> getMap(AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> SqlHelper.getObject(log, baseMapper.selectMaps(queryWrapper)));
+    }
+
+    /**
+     * 查询总记录数
+     *
+     * @param entityClass 实体类
+     * @see Wrappers#emptyWrapper()
+     */
+    public static <T> long count(Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectCount(null));
+    }
+
+    /**
+     * 根据 Wrapper 条件,查询总记录数
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> long count(AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> baseMapper.selectCount(queryWrapper));
+    }
+
+    /**
+     * 查询列表
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> List<T> list(AbstractWrapper<T, ?, ?> queryWrapper) {
+        Class<T> entityClass = getEntityClass(queryWrapper);
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectList(queryWrapper));
+    }
+
+    /**
+     * 查询所有
+     *
+     * @param entityClass 实体类
+     * @see Wrappers#emptyWrapper()
+     */
+    public static <T> List<T> list(Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectList(null));
+    }
+
+    /**
+     * 查询列表
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> List<Map<String, Object>> listMaps(AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> baseMapper.selectMaps(queryWrapper));
+    }
+
+    /**
+     * 查询所有列表
+     *
+     * @param entityClass 实体类
+     * @see Wrappers#emptyWrapper()
+     */
+    public static <T> List<Map<String, Object>> listMaps(Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectMaps(null));
+    }
+
+    /**
+     * 查询全部记录
+     *
+     * @param entityClass 实体类
+     */
+    public static <T> List<T> listObjs(Class<T> entityClass) {
+        return listObjs(entityClass, i -> i);
+    }
+
+    /**
+     * 根据 Wrapper 条件,查询全部记录
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> List<Object> listObjs(AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> baseMapper.selectObjs(queryWrapper));
+    }
+
+    /**
+     * 根据 Wrapper 条件,查询全部记录
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     * @param mapper       转换函数
+     */
+    public static <T, V> List<V> listObjs(AbstractWrapper<T, ?, ?> queryWrapper, SFunction<? super T, V> mapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> baseMapper.selectList(queryWrapper).stream().map(mapper).collect(Collectors.toList()));
+    }
+
+    /**
+     * 查询全部记录
+     *
+     * @param entityClass 实体类
+     * @param mapper      转换函数
+     */
+    public static <T, V> List<V> listObjs(Class<T> entityClass, SFunction<? super T, V> mapper) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectList(null).stream().map(mapper).collect(Collectors.toList()));
+    }
+
+    /**
+     * 无条件翻页查询
+     *
+     * @param page        翻页对象
+     * @param entityClass 实体类
+     * @see Wrappers#emptyWrapper()
+     */
+    public static <T, E extends IPage<Map<String, Object>>> E pageMaps(E page, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectMapsPage(page, null));
+    }
+
+    /**
+     * 翻页查询
+     *
+     * @param page         翻页对象
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T, E extends IPage<Map<String, Object>>> E pageMaps(E page, AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> baseMapper.selectMapsPage(page, queryWrapper));
+    }
+
+    /**
+     * 无条件翻页查询
+     *
+     * @param page        翻页对象
+     * @param entityClass 实体类
+     * @see Wrappers#emptyWrapper()
+     */
+    public static <T> IPage<T> page(IPage<T> page, Class<T> entityClass) {
+        return SqlHelper.execute(entityClass, baseMapper -> baseMapper.selectPage(page, null));
+    }
+
+    /**
+     * 翻页查询
+     *
+     * @param page         翻页对象
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     */
+    public static <T> IPage<T> page(IPage<T> page, AbstractWrapper<T, ?, ?> queryWrapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> baseMapper.selectPage(page, queryWrapper));
+    }
+
+    /**
+     * 链式查询 普通
+     *
+     * @return QueryWrapper 的包装类
+     */
+    public static <T> QueryChainWrapper<T> query(Class<T> entityClass) {
+        return ChainWrappers.queryChain(entityClass);
+    }
+
+    /**
+     * 链式查询 lambda 式
+     * <p>注意:不支持 Kotlin </p>
+     *
+     * @return LambdaQueryWrapper 的包装类
+     */
+    public static <T> LambdaQueryChainWrapper<T> lambdaQuery(Class<T> entityClass) {
+        return ChainWrappers.lambdaQueryChain(entityClass);
+    }
+
+    /**
+     * 链式更改 普通
+     *
+     * @return UpdateWrapper 的包装类
+     */
+    public static <T> UpdateChainWrapper<T> update(Class<T> entityClass) {
+        return ChainWrappers.updateChain(entityClass);
+    }
+
+    /**
+     * 链式更改 lambda 式
+     * <p>注意:不支持 Kotlin </p>
+     *
+     * @return LambdaUpdateWrapper 的包装类
+     */
+    public static <T> LambdaUpdateChainWrapper<T> lambdaUpdate(Class<T> entityClass) {
+        return ChainWrappers.lambdaUpdateChain(entityClass);
+    }
+
+    /**
+     * <p>
+     * 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
+     * 此次修改主要是减少了此项业务代码的代码量(存在性验证之后的saveOrUpdate操作)
+     * </p>
+     *
+     * @param entity 实体对象
+     */
+    public static <T> boolean saveOrUpdate(T entity, AbstractWrapper<T, ?, ?> updateWrapper) {
+        return update(entity, updateWrapper) || saveOrUpdate(entity);
+    }
+
+    /**
+     * 根据 Wrapper,查询一条记录
+     *
+     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
+     * @param mapper       转换函数
+     */
+    public static <T, V> V getObj(AbstractWrapper<T, ?, ?> queryWrapper, SFunction<? super T, V> mapper) {
+        return SqlHelper.execute(getEntityClass(queryWrapper), baseMapper -> mapper.apply(baseMapper.selectOne(queryWrapper)));
+    }
+
+    /**
+     * 从集合中获取实体类型
+     *
+     * @param entityList 实体集合
+     * @param <T>        实体类型
+     * @return 实体类型
+     */
+    @SuppressWarnings("unchecked")
+    private static <T> Class<T> getEntityClass(Collection<T> entityList) {
+        Class<T> entityClass = null;
+        for (T entity : entityList) {
+            if (entity != null && entity.getClass() != null) {
+                entityClass = (Class<T>) entity.getClass();
+                break;
+            }
+        }
+        Assert.notNull(entityClass, "error: can not get entityClass from entityList");
+        return entityClass;
+    }
+
+    /**
+     * 从wrapper中尝试获取实体类型
+     *
+     * @param queryWrapper 条件构造器
+     * @param <T>          实体类型
+     * @return 实体类型
+     */
+    @SuppressWarnings("unchecked")
+    private static <T> Class<T> getEntityClass(AbstractWrapper<T, ?, ?> queryWrapper) {
+        Class<T> entityClass = queryWrapper.getEntityClass();
+        if (entityClass == null) {
+            T entity = queryWrapper.getEntity();
+            if (entity != null) {
+                entityClass = (Class<T>) entity.getClass();
+            }
+        }
+        Assert.notNull(entityClass, "error: can not get entityClass from wrapper");
+        return entityClass;
+    }
+
+    /**
+     * 获取表信息,获取不到报错提示
+     *
+     * @param entityClass 实体类
+     * @param <T>         实体类型
+     * @return 对应表信息
+     */
+    private static <T> TableInfo getTableInfo(Class<T> entityClass) {
+        return Optional.ofNullable(TableInfoHelper.getTableInfo(entityClass)).orElseThrow(() -> ExceptionUtils.mpe("error: can not find TableInfo from Class: \"%s\".", entityClass.getName()));
+    }
+}

+ 4 - 0
mybatis-plus-extension/src/main/kotlin/com/baomidou/mybatisplus/extension/kotlin/KtQueryChainWrapper.kt

@@ -55,4 +55,8 @@ open class KtQueryChainWrapper<T : Any>(
         return baseMapper
     }
 
+    override fun getEntityClass(): Class<T> {
+        return super.wrapperChildren.entityClass
+    }
+
 }

+ 4 - 0
mybatis-plus-extension/src/main/kotlin/com/baomidou/mybatisplus/extension/kotlin/KtUpdateChainWrapper.kt

@@ -53,4 +53,8 @@ open class KtUpdateChainWrapper<T : Any>(
         return baseMapper
     }
 
+    override fun getEntityClass(): Class<T> {
+        return super.wrapperChildren.entityClass
+    }
+
 }

+ 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;
+    }
+}

Some files were not shown because too many files changed in this diff