28 Incheckningar 3c7ee002b8 ... 3e0029a455

Upphovsman SHA1 Meddelande Datum
  nieqiurong 3e0029a455 更新快照. 1 månad sedan
  nieqiurong 51e7693408 调整getSqlSessionFactory获取. 1 månad sedan
  nieqiurong 7f5936d894 使用确定的类加载器加载. 1 månad sedan
  nieqiurong 81165f567e 同步生成代码. 1 månad sedan
  nieqiurong 690e56ed0d 处理PRIMARY_KEY_主键索引情况. 1 månad sedan
  nieqiurong a0e2ed0b6a 支持自定义SqlSessionTemplate 1 månad sedan
  nieqiurong d603ed4c91 切换oracle驱动为中央仓库托管. 1 månad sedan
  nieqiurong e7c8876d11 调整参数组装方法(支持子类复用) 1 månad sedan
  nieqiurong c7679155ed 改进参数提取. 1 månad sedan
  nieqiurong 6e0e064214 更新快照. 1 månad sedan
  nieqiurong 49a5f3473f 调整SqlRuuner(方法实现类复用,支持处理单数组). 1 månad sedan
  nieqiurong f4ed853dbd 支持SqlRunner单参数属性提取. 2 månader sedan
  nieqiurong 3c2eff549e 增加手动指定CompatibleSet实现方法. 2 månader sedan
  nieqiurong c257d24488 发布3.5.12-SNAPSHOT. 2 månader sedan
  nieqiurong 44bab1fc6c 重构SqlRunner执行SQL. 2 månader sedan
  nieqiurong 76c159b368 解决CompatibleSet初始化存在的多线程安全问题. 2 månader sedan
  nieqiurong fcaf4fc28b 增加生成示例代码版本管理. 2 månader sedan
  nieqiurong 7eb164f2d4 调整代码生成器模板 2 månader sedan
  nieqiurong 580a5530fd 更新版本号. 2 månader sedan
  程序员小墨 dfc8f62c55 update `entity.java.ftl`: import 与类注释之间应有1个空行 (与其他模板保持一致) 2 månader sedan
  nieqiurong 7cfa499dde 发布3.5.11 2 månader sedan
  nieqiurong 41633e801d 更新版本发布示例. 2 månader sedan
  nieqiurong aca07ad2cb 更新注释. 2 månader sedan
  nieqiurong 78e9a35343 调整动态表解析处理(处理UnsupportedStatement与DDL语法). 2 månader sedan
  nieqiurong e99586c4bc 更新快照. 2 månader sedan
  nieqiurong f27ff56a58 同步动态表处理器. 2 månader sedan
  nieqiurong df9239e5bc 修复创建索引获取表错误. 2 månader sedan
  nieqiurong 8cd0353687 修复非法SQL拦截插件索引信息读取问题. 2 månader sedan
100 ändrade filer med 3530 tillägg och 292 borttagningar
  1. 35 0
      CHANGELOG.md
  2. 2 2
      build.gradle
  3. 15 25
      changelog-temp.md
  4. 1 1
      gradle.properties
  5. BIN
      libs/ojdbc8.jar
  6. 2 0
      mybatis-plus-core/build.gradle
  7. 151 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/assist/AbstractSqlRunner.java
  8. 115 1
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/assist/ISqlRunner.java
  9. 16 6
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/SqlRunnerInjector.java
  10. 16 11
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java
  11. 11 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringUtils.java
  12. 50 17
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/TableNameParser.java
  13. 76 0
      mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtilsTest.java
  14. 28 0
      mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/toolkit/TableNameParserTest.java
  15. 50 5
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spi/CompatibleHelper.java
  16. 4 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spi/CompatibleSet.java
  17. 10 1
      mybatis-plus-generator/build.gradle
  18. 6 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/ConstVal.java
  19. 12 0
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/index/AbstractMapperMethodHandler.java
  20. 2 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/index/DefaultGenerateMapperLambdaMethodHandler.java
  21. 2 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/index/DefaultGenerateMapperMethodHandler.java
  22. 0 1
      mybatis-plus-generator/src/main/resources/templates/controller.java.ej
  23. 0 1
      mybatis-plus-generator/src/main/resources/templates/controller.java.vm
  24. 4 4
      mybatis-plus-generator/src/main/resources/templates/entity.java.btl
  25. 3 3
      mybatis-plus-generator/src/main/resources/templates/entity.java.ej
  26. 2 1
      mybatis-plus-generator/src/main/resources/templates/entity.java.ftl
  27. 3 3
      mybatis-plus-generator/src/main/resources/templates/entity.java.vm
  28. 6 7
      mybatis-plus-generator/src/main/resources/templates/entity.kt.btl
  29. 2 2
      mybatis-plus-generator/src/main/resources/templates/entity.kt.ej
  30. 2 2
      mybatis-plus-generator/src/main/resources/templates/entity.kt.vm
  31. 0 1
      mybatis-plus-generator/src/main/resources/templates/mapper.java.ftl
  32. 2 2
      mybatis-plus-generator/src/main/resources/templates/serviceImpl.java.ej
  33. 18 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/controller/SimpleController.java
  34. 155 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/entity/Simple.java
  35. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/mapper/SimpleMapper.java
  36. 5 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/mapper/xml/SimpleMapper.xml
  37. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/service/ISimpleService.java
  38. 20 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/service/impl/SimpleServiceImpl.java
  39. 18 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/controller/SimpleController.java
  40. 155 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/entity/Simple.java
  41. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/mapper/SimpleMapper.java
  42. 5 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/mapper/xml/SimpleMapper.xml
  43. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/service/ISimpleService.java
  44. 20 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/service/impl/SimpleServiceImpl.java
  45. 18 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/controller/SimpleController.java
  46. 155 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/entity/Simple.java
  47. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/mapper/SimpleMapper.java
  48. 5 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/mapper/xml/SimpleMapper.xml
  49. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/service/ISimpleService.java
  50. 20 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/service/impl/SimpleServiceImpl.java
  51. 18 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/controller/SimpleController.java
  52. 155 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/entity/Simple.java
  53. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/mapper/SimpleMapper.java
  54. 5 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/mapper/xml/SimpleMapper.xml
  55. 16 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/service/ISimpleService.java
  56. 20 0
      mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/service/impl/SimpleServiceImpl.java
  57. 18 0
      mybatis-plus-generator/src/test/java/com/baomidou/mybatisplus/generator/index/MapperMethodHandlerTest.java
  58. 53 0
      mybatis-plus-generator/src/test/java/com/baomidou/mybatisplus/generator/samples/H2CodeGeneratorTest.java
  59. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/controller/SimpleController.kt
  60. 80 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/entity/Simple.kt
  61. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/mapper/SimpleMapper.kt
  62. 5 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/mapper/xml/SimpleMapper.xml
  63. 14 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/service/ISimpleService.kt
  64. 20 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/service/impl/SimpleServiceImpl.kt
  65. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/controller/SimpleController.kt
  66. 80 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/entity/Simple.kt
  67. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/mapper/SimpleMapper.kt
  68. 5 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/mapper/xml/SimpleMapper.xml
  69. 14 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/service/ISimpleService.kt
  70. 20 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/service/impl/SimpleServiceImpl.kt
  71. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/controller/SimpleController.kt
  72. 80 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/entity/Simple.kt
  73. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/mapper/SimpleMapper.kt
  74. 5 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/mapper/xml/SimpleMapper.xml
  75. 14 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/service/ISimpleService.kt
  76. 20 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/service/impl/SimpleServiceImpl.kt
  77. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/controller/SimpleController.kt
  78. 80 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/entity/Simple.kt
  79. 16 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/mapper/SimpleMapper.kt
  80. 5 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/mapper/xml/SimpleMapper.xml
  81. 14 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/service/ISimpleService.kt
  82. 20 0
      mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/service/impl/SimpleServiceImpl.kt
  83. 89 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/DynamicTableNameHandler.java
  84. 3 1
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/parser/JsqlParserGlobal.java
  85. 0 104
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameInnerInterceptor.java
  86. 89 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptor.java
  87. 39 22
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java
  88. 271 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptorTest.java
  89. 12 2
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/IllegalSQLInnerInterceptorTest.java
  90. 90 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/DynamicTableNameHandler.java
  91. 3 1
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/parser/JsqlParserGlobal.java
  92. 89 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptor.java
  93. 24 25
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java
  94. 272 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptorTest.java
  95. 13 2
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/IllegalSQLInnerInterceptorTest.java
  96. 25 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/DynamicTableNameHandler.java
  97. 3 1
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/parser/JsqlParserGlobal.java
  98. 12 24
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptor.java
  99. 34 12
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java
  100. 239 0
      mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptorTest.java

+ 35 - 0
CHANGELOG.md

@@ -1,4 +1,39 @@
 # CHANGELOG
+## [v3.5.11] 2025.03.23
+- fix: 修复代码生成器链式模型非`lombok`下生成了`@Accessors`注解
+- fix: 修复主键使用`UUID`执行批量删除错
+- fix: 修复`Kotlin`使用`select(predicate)`方法错误
+- fix: 修复`AbstractCaffeineJsqlParseCache`异步产生的错误
+- fix: 修复动态SQL解析包含SQL注释(--或#)导致的合并错误 (动态脚本语句不再处理换行,如果需要去除换行请自行处理)
+- fix: 修复`DataChangeRecorderInnerInterceptor`数据比较出现强转异常
+- fix: 修复`IllegalSQLInnerInterceptor`拦截插件获取`catalog`与`schema`错误
+- fix: 修复动态表解析`create table if not exists` 获取表名错误
+- fix: 修复动态表解析`create [type] index` 获取表名错误
+- feat: 新增`DynamicTableNameJsqlParserInnerInterceptor` 基于`JsqlParser`动态表处理
+- feat: 支持`DdlScript`自定义脚本运行器参数
+- feat: 支持`DdlHelper`自定义脚本运行器参数
+- feat: 支持`DdlApplicationRunner`参数配置(脚本错误处理,自定义`ScriptRunner`,多处理器执行异常是否中断)
+- feat: 支持`BaseMultiTableInnerInterceptor`指定追加条件模式 (默认条件追加至末尾,仅作用于`select`,`delete`,`update`)
+- feat: 支持生成器`Entity`指定`serialVersionUID`添加`@Serial`注解
+- feat: 支持生成器`Entity`注解(字段,类注解)自定义处理
+- feat: 支持生成器`Entity`导包自定义处理
+- feat: 支持`崖山`数据库
+- feat: 支持`Hive2`分页
+- feat: 升级`Gradle`至8.10
+- feat: 支持`DdlHelper`执行自定义异常处理
+- opt: 调整`DynamicTableNameInnerInterceptor`表处理逻辑并保证`hook`运行
+- opt: 调整`DdlScript`类方法实现(分离DDL版本记录,优化执行方法)
+- opt: 调整`DbType#GAUSS`数据库名为`gauss`
+- opt: 调整`JsqlParserGlobal`解析线程池指定
+- opt: 移除过时的`FieldStrategy.IGNORED`
+- opt: 移除过时的`GlobalConfig.DbConfig#selectStrategy`
+- opt: 移除过时的`MybatisSqlSessionFactoryBean#typeEnumsPackage`
+- opt: 优化`DdlHelper`资源加载(不再依赖`Spring`或者其他实现)
+- opt: 去除`DdlHelper`中`getScriptRunner`方法指定的字符集编码
+- doc: 修正`DdlHelper`中注释错误
+由于`jsqlParser`5.0版本与5.1版本升级不兼容性不是很大,计划后期移除`mybatis-plus-jsqlparser-5.0`支持模块。
+多版本支持相对来说比较麻烦,后期只维护`mybatis-plus-jsqlparser-4.9` 与 `mybatis-plus-jsqlparser`(保持最新版跟进,直到再提升jdk)
+
 ## [v3.5.10.1] 2025.01.13
 - fix: 修复动态节点处理错误
 

+ 2 - 2
build.gradle

@@ -54,7 +54,7 @@ ext {
         "p6spy"                      : "p6spy:p6spy:3.9.1",
         "sqlserver"                  : "com.microsoft.sqlserver:sqljdbc4:4.0",
         "postgresql"                 : "org.postgresql:postgresql:42.7.4",
-        "oracle"                     : fileTree(dir: 'libs', includes: ['ojdbc8.jar']),
+        "oracle"                     : "com.oracle.database.jdbc:ojdbc8:23.7.0.25.01",
         "dm"                         : fileTree(dir: 'libs', includes: ["jdbcDriver-18.jar"]),
         "h2"                         : "com.h2database:h2:2.3.232",
         "mysql"                      : "com.mysql:mysql-connector-j:9.0.0",
@@ -201,7 +201,7 @@ subprojects {
             }
         }
 
-        // use example : ./gradlew clean build publish publishToMavenCentralPortal -DauthToken='xxxxxx' -x test
+        // use example : ./gradlew clean build publishMavenJavaPublicationToLocalRepository publishToMavenCentralPortal -DauthToken='xxxxxx' -x test
         mavenCentral {
             repoDir = layout.buildDirectory.dir('repos/bundles')
             // Base64 encoded of "username:password"

+ 15 - 25
changelog-temp.md

@@ -1,26 +1,16 @@
-- fix: 修复链式模型生成错误
-- fix: 修复`UUID`主键执行批量删除错
-- fix: 修复`Kotlin`使用`select(predicate)`方法错误
-- fix: 修复`AbstractCaffeineJsqlParseCache`异步产生的错误
-- fix: 修复动态SQL解析包含SQL注释(--或#)导致的合并错误
-- fix: 修复`DataChangeRecorderInnerInterceptor`数据比较出现强转异常
-- feat: 支持`DDL`自定义脚本运行器参数
-- feat: 支持`DdlApplicationRunner`参数配置(脚本错误处理,自定义ScriptRunner,多处理器执行异常是否中断)
-- feat: 支持`BaseMultiTableInnerInterceptor`指定追加条件模式 (默认条件追加至末尾,仅作用于select,delete,update)
-- feat: 支持生成器`Entity`指定`serialVersionUID`添加`@Serial`注解
-- feat: 支持生成器`Entity`注解(字段,类注解)自定义处理
-- feat: 支持生成器`Entity`导包自定义处理
-- feat: 支持崖山数据库
-- feat: 支持`Hive2`分页
-- feat: 升级`Gradle`至8.10
-- feat: 支持`DdlHelper`执行自定义异常处理
-- opt: 调整`DdlScript`类方法实现(分离DDL版本记录,优化执行方法)
-- opt: 调整`DbType#GAUSS`数据库名为gauss
-- opt: 调整`JsqlParser`解析线程池指定
-- opt: 移除过时的`FieldStrategy.IGNORED`
-- opt: 移除过时的`GlobalConfig.DbConfig#selectStrategy`
-- opt: 移除过时的`MybatisSqlSessionFactoryBean#typeEnumsPackage`
-- opt: 优化`DdlHelper`资源加载(不再依赖spring或者其他实现)
-- opt: 去除`DdlHelper`中getScriptRunner方法指定的字符集编码
-- doc: 修正`DdlHelper`中注释错误
+- fix: 修复批量操作异步执行首次出现`NoSuchElementException`错误
+- fix: 修复`entity.java.btl`生成`toString`方法样式错误
+- fix: 修复`entity.java.ftl`模板类注释与导包缺少换行
+- opt: 支持手动指定`CompatibleSet`实现
+- opt: 去除`entity.kt.btl`模板`@Override`注解
+- opt: 解决`serviceImpl.java.ej`生成格式不统一
+- opt: 去除`mapper.java.ftl`多余的换行生成
+- opt: 去除`entity.kt.vm`,`entity.kt.ej`,`entity.kt.btl`导包结束分隔符
+- opt: 去除`controller.java.ej`,`controller.java.vm`多余的换行
+- opt: 去除`entity.kt.btl`生成属性多余的空格
+- opt: 代码生成器处理`PRIMARY_KEY_`为开头的主键索引情况
+- opt: 统一`entity.java.btl`,`entity.java.ej`,`entity.java.ftl`,`entity.java.vm` 生成的`toString`方法样式
+- opt: 重构`SqlRunner`执行`SQL`语句 (动态传参,不再根据参数值生成执行`SQL`)
+- opt: 增强`SqlRunner`执行(支持单参数使用`Map`({key}),`List`({index}),`JavaBean`({property})获取值)
+- opt: 改进`MybatisUtils`对自`SqlSessionFactory`的提取(支持自定义sqlSessionTemplate子类)
 -

+ 1 - 1
gradle.properties

@@ -1,4 +1,4 @@
-APP_VERSION=3.5.11-SNAPSHOT
+APP_VERSION=3.5.12-SNAPSHOT
 APP_GROUP=com.baomidou
 signing.keyId=1FD337F9
 signing.password=243194995

BIN
libs/ojdbc8.jar


+ 2 - 0
mybatis-plus-core/build.gradle

@@ -7,4 +7,6 @@ dependencies {
     implementation "${lib.'imadcn'}"
 
     testImplementation "${lib.'logback-classic'}"
+    testImplementation "${lib."mybatis-spring"}"
+    testImplementation "${lib.'spring-jdbc'}"
 }

+ 151 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/assist/AbstractSqlRunner.java

@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2011-2025, 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.core.assist;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import org.apache.ibatis.parsing.GenericTokenParser;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import static com.baomidou.mybatisplus.core.toolkit.StringPool.DOT;
+import static com.baomidou.mybatisplus.core.toolkit.StringPool.HASH_LEFT_BRACE;
+import static com.baomidou.mybatisplus.core.toolkit.StringPool.LEFT_BRACE;
+import static com.baomidou.mybatisplus.core.toolkit.StringPool.LEFT_SQ_BRACKET;
+import static com.baomidou.mybatisplus.core.toolkit.StringPool.RIGHT_BRACE;
+import static com.baomidou.mybatisplus.core.toolkit.StringPool.RIGHT_SQ_BRACKET;
+
+/**
+ * @author nieqiurong
+ * @since 3.5.12
+ */
+public abstract class AbstractSqlRunner implements ISqlRunner {
+
+    /**
+     * 默认分词处理器
+     *
+     * @since 3.5.12
+     */
+    private static final GenericTokenParser DEFAULT_TOKEN_PARSER = new GenericTokenParser(LEFT_BRACE, RIGHT_BRACE, content -> HASH_LEFT_BRACE + content + RIGHT_BRACE);
+
+    /**
+     * 校验索引正则
+     *
+     * @since 3.5.12
+     */
+    private static final Pattern INDEX_PATTERN = Pattern.compile("^\\d+$");
+
+    /**
+     * 第一个值参数key
+     *
+     * @since 3.5.12
+     */
+    private static final String ARG0 = "arg0";
+
+
+    /**
+     * 获取执行语句 (将原始占位符语句转换为标准占位符语句)
+     *
+     * @param sql  原始sql
+     * @param args 参数
+     * @return 执行语句 (带参数占位符)
+     * @since 3.5.12
+     */
+    protected String parse(String sql, Object... args) {
+        if (args != null && args.length == 1) {
+            Object arg = args[0];
+            Class<?> clazz = arg.getClass();
+            return new GenericTokenParser(LEFT_BRACE, RIGHT_BRACE, content -> {
+                if (INDEX_PATTERN.matcher(content).matches()) {
+                    if (arg instanceof Collection || clazz.isArray()) {
+                        return HASH_LEFT_BRACE + ARG0 + LEFT_SQ_BRACKET + content + RIGHT_SQ_BRACKET + RIGHT_BRACE;
+                    }
+                    return HASH_LEFT_BRACE + content + RIGHT_BRACE;
+                } else {
+                    return HASH_LEFT_BRACE + ARG0 + DOT + content + RIGHT_BRACE;
+                }
+            }).parse(sql);
+        }
+        return DEFAULT_TOKEN_PARSER.parse(sql);
+    }
+
+    /**
+     * 获取参数列表
+     *
+     * @param args 参数(单参数时,支持使用Map,List,Array,JavaBean访问)
+     * @return 参数map
+     * @since 3.5.12
+     */
+    protected Map<String, Object> getParams(Object... args) {
+        if (args != null && args.length > 0) {
+            Map<String, Object> params = CollectionUtils.newHashMapWithExpectedSize(args.length);
+            for (int i = 0; i < args.length; i++) {
+                Object arg = args[i];
+                if (i == 0) {
+                    params.put(ARG0, arg);
+                }
+                params.put(String.valueOf(i), arg);
+            }
+            return params;
+        }
+        return new HashMap<>();
+    }
+
+    /**
+     * 获取sqlMap参数
+     * <p>
+     * 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean)
+     * <li>当参数为 Map 时可通过{key}进行属性访问
+     * <li>当参数为 JavaBean 时可通过{property}进行属性访问
+     * <li>当参数为 List 时直接访问索引 {0} </li>
+     * <li>当参数为 Array 时直接访问索引 {0} </li>
+     * </p>
+     *
+     * @param sql  指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 参数集合
+     */
+    protected Map<String, Object> sqlMap(String sql, Object... args) {
+        Map<String, Object> sqlMap = getParams(args);
+        sqlMap.put(SQL, parse(sql, args));
+        return sqlMap;
+    }
+
+    /**
+     * <p>
+     * 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean)
+     * <li>当参数为 Map 时可通过{key}进行属性访问
+     * <li>当参数为 JavaBean 时可通过{property}进行属性访问
+     * <li>当参数为 List 时直接访问索引 {0} </li>
+     * <li>当参数为 Array 时直接访问索引 {0} </li>
+     * </p>
+     *
+     * @param sql  指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param page 分页模型
+     * @param args 参数
+     * @return 参数集合
+     */
+    protected Map<String, Object> sqlMap(String sql, IPage<?> page, Object... args) {
+        Map<String, Object> sqlMap = getParams(args);
+        sqlMap.put(PAGE, page);
+        sqlMap.put(SQL, parse(sql, args));
+        return sqlMap;
+    }
+
+}

+ 115 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/assist/ISqlRunner.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.core.assist;
 
+import com.baomidou.mybatisplus.core.injector.SqlRunnerInjector;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
 import java.util.List;
@@ -22,37 +23,150 @@ import java.util.Map;
 
 /**
  * SqlRunner执行接口
+ * <p>
+ * 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean)
+ * <li>当参数为 Map 时可通过{key}进行属性访问
+ * <li>当参数为 JavaBean 时可通过{property}进行属性访问
+ * <li>当参数为 List 时直接访问索引 {0} </li>
+ * <li>当参数为 Array 时直接访问索引 {0} </li>
+ * </p>
  *
- * @author yuxiaobin
+ * @author yuxiaobin, nieqiurong
  * @since 2018/2/7
  */
 public interface ISqlRunner {
 
+    /**
+     * INSERT 语句
+     */
     String INSERT = "com.baomidou.mybatisplus.core.mapper.SqlRunner.Insert";
+
+    /**
+     * DELETE 语句
+     */
     String DELETE = "com.baomidou.mybatisplus.core.mapper.SqlRunner.Delete";
+
+    /**
+     * UPDATE 语句
+     */
     String UPDATE = "com.baomidou.mybatisplus.core.mapper.SqlRunner.Update";
+
+    /**
+     * SELECT_LIST 语句
+     */
     String SELECT_LIST = "com.baomidou.mybatisplus.core.mapper.SqlRunner.SelectList";
+
+    /**
+     * SELECT_OBJS 语句
+     */
     String SELECT_OBJS = "com.baomidou.mybatisplus.core.mapper.SqlRunner.SelectObjs";
+
+    /**
+     * COUNT 语句
+     */
     String COUNT = "com.baomidou.mybatisplus.core.mapper.SqlRunner.Count";
+
+    /**
+     * 注入SQL脚本
+     *
+     * @deprecated 3.5.12 {@link SqlRunnerInjector#SQL_SCRIPT}
+     */
+    @Deprecated
     String SQL_SCRIPT = "${sql}";
+
+    /**
+     * sql访问参数
+     */
     String SQL = "sql";
+
+    /**
+     * page访问参数
+     */
     String PAGE = "page";
 
+    /**
+     * 执行插入语句
+     *
+     * @param sql  指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 插入结果
+     */
     boolean insert(String sql, Object... args);
 
+    /**
+     * 执行删除语句
+     *
+     * @param sql  指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 删除结果
+     */
     boolean delete(String sql, Object... args);
 
+    /**
+     * 执行更新语句
+     *
+     * @param sql  指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 更新结果
+     */
     boolean update(String sql, Object... args);
 
+    /**
+     * 根据sql查询Map结果集
+     * <p>SqlRunner.db().selectList("select * from tbl_user where name={0}", "Caratacus")</p>
+     *
+     * @param sql  sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数列表
+     * @return 结果集
+     */
     List<Map<String, Object>> selectList(String sql, Object... args);
 
+    /**
+     * 根据sql查询一个字段值的结果集
+     * <p>注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@link #selectList(String, Object...)}</p>
+     *
+     * @param sql  sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 结果集
+     */
     List<Object> selectObjs(String sql, Object... args);
 
+    /**
+     * 根据sql查询一个字段值的一条结果
+     * <p>注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@link #selectOne(String, Object...)}</p>
+     *
+     * @param sql  sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 结果
+     */
     Object selectObj(String sql, Object... args);
 
+    /**
+     * 查询总数
+     *
+     * @param sql  sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 总记录数
+     */
     long selectCount(String sql, Object... args);
 
+    /**
+     * 获取单条记录
+     *
+     * @param sql  sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @return 单行结果集 (当执行语句返回多条记录时,只会选取第一条记录)
+     */
     Map<String, Object> selectOne(String sql, Object... args);
 
+    /**
+     * 分页查询
+     *
+     * @param page 分页对象
+     * @param sql  sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
+     * @param args 参数
+     * @param <E>  E
+     * @return 分页数据
+     */
     <E extends IPage<Map<String, Object>>> E selectPage(E page, String sql, Object... args);
 }

+ 16 - 6
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/SqlRunnerInjector.java

@@ -41,6 +41,16 @@ public class SqlRunnerInjector {
     protected Configuration configuration;
     protected LanguageDriver languageDriver;
 
+    /**
+     * 注入动态执行脚本
+     *
+     * @since 3.5.12
+     */
+    public static final String SQL_SCRIPT = "<script>" +
+        "${sql}\n" +
+        "<if test=\"true\"></if>" +
+        "</script>";
+
 
     public void inject(Configuration configuration) {
         this.configuration = configuration;
@@ -109,7 +119,7 @@ public class SqlRunnerInjector {
             logger.warn("MappedStatement 'SqlRunner.SelectList' Already Exists");
             return;
         }
-        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SQL_SCRIPT, Map.class);
         createSelectMappedStatement(ISqlRunner.SELECT_LIST, sqlSource, Map.class);
     }
 
@@ -121,7 +131,7 @@ public class SqlRunnerInjector {
             logger.warn("MappedStatement 'SqlRunner.SelectObjs' Already Exists");
             return;
         }
-        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Object.class);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SQL_SCRIPT, Object.class);
         createSelectMappedStatement(ISqlRunner.SELECT_OBJS, sqlSource, Object.class);
     }
 
@@ -133,7 +143,7 @@ public class SqlRunnerInjector {
             logger.warn("MappedStatement 'SqlRunner.Count' Already Exists");
             return;
         }
-        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SQL_SCRIPT, Map.class);
         createSelectMappedStatement(ISqlRunner.COUNT, sqlSource, Long.class);
     }
 
@@ -145,7 +155,7 @@ public class SqlRunnerInjector {
             logger.warn("MappedStatement 'SqlRunner.Insert' Already Exists");
             return;
         }
-        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SQL_SCRIPT, Map.class);
         createUpdateMappedStatement(ISqlRunner.INSERT, sqlSource, SqlCommandType.INSERT);
     }
 
@@ -157,7 +167,7 @@ public class SqlRunnerInjector {
             logger.warn("MappedStatement 'SqlRunner.Update' Already Exists");
             return;
         }
-        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SQL_SCRIPT, Map.class);
         createUpdateMappedStatement(ISqlRunner.UPDATE, sqlSource, SqlCommandType.UPDATE);
     }
 
@@ -169,7 +179,7 @@ public class SqlRunnerInjector {
             logger.warn("MappedStatement 'SqlRunner.Delete' Already Exists");
             return;
         }
-        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SQL_SCRIPT, Map.class);
         createUpdateMappedStatement(ISqlRunner.DELETE, sqlSource, SqlCommandType.DELETE);
     }
 }

+ 16 - 11
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java

@@ -1,10 +1,14 @@
 package com.baomidou.mybatisplus.core.toolkit;
 
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
 import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
 import lombok.experimental.UtilityClass;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.apache.ibatis.session.defaults.DefaultSqlSession;
@@ -58,25 +62,26 @@ public class MybatisUtils {
 
     /**
      * 获取SqlSessionFactory
+     * <p>当自定义实现{@link SqlSession}时,请实现对{@link SqlSessionFactory}的访问 (spring的方式)</p>
+     * <p>当无法获得{@link SqlSessionFactory}时,需要将{@link SqlSessionFactory}绑定至上下文对象中(原生mybatis访问方式)</p>
      *
      * @param mybatisMapperProxy {@link MybatisMapperProxy}
      * @return SqlSessionFactory
+     * @see DefaultSqlSession
+     * @see GlobalConfigUtils#getGlobalConfig(Configuration)
+     * @see GlobalConfigUtils#setGlobalConfig(Configuration, GlobalConfig)
      * @since 3.5.7
      */
     public static SqlSessionFactory getSqlSessionFactory(MybatisMapperProxy<?> mybatisMapperProxy) {
         SqlSession sqlSession = mybatisMapperProxy.getSqlSession();
-        if (sqlSession instanceof DefaultSqlSession) {
-            // TODO 原生mybatis下只能这样了.
-            return GlobalConfigUtils.getGlobalConfig(mybatisMapperProxy.getSqlSession().getConfiguration()).getSqlSessionFactory();
-        }
-        Field declaredField;
-        try {
-            declaredField = sqlSession.getClass().getDeclaredField("sqlSessionFactory");
-            declaredField.setAccessible(true);
-            return (SqlSessionFactory) declaredField.get(sqlSession);
-        } catch (NoSuchFieldException | IllegalAccessException e) {
-            throw new RuntimeException(e);
+        MetaObject metaObject = SystemMetaObject.forObject(sqlSession);
+        String property = "sqlSessionFactory";
+        if (metaObject.hasGetter(property)) {
+            return (SqlSessionFactory) metaObject.getValue(property);
         }
+        SqlSessionFactory sqlSessionFactory = GlobalConfigUtils.getGlobalConfig(mybatisMapperProxy.getSqlSession().getConfiguration()).getSqlSessionFactory();
+        Assert.isTrue(sqlSessionFactory != null, "Please implement access to the sqlSessionFactory property or bind sqlSessionFactory to global access.");
+        return sqlSessionFactory;
     }
 
     /**

+ 11 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringUtils.java

@@ -226,7 +226,9 @@ public final class StringUtils {
      *
      * @param content 填充内容
      * @param args    填充参数
+     * @deprecated 3.5.12
      */
+    @Deprecated
     public static String sqlArgsFill(String content, Object... args) {
         if (StringUtils.isNotBlank(content) && ArrayUtils.isNotEmpty(args)) {
             // 索引不能使用,因为 SQL 中的占位符数字与索引不相同
@@ -246,7 +248,9 @@ public final class StringUtils {
      * @param ptn      需要替换部分的正则表达式
      * @param replacer 替换处理器
      * @return 返回字符串构建起
+     * @deprecated 3.5.12
      */
+    @Deprecated
     public static StringBuilder replace(CharSequence src, Pattern ptn, BiIntFunction<Matcher, CharSequence> replacer) {
         int idx = 0, last = 0, len = src.length();
         Matcher m = ptn.matcher(src);
@@ -267,7 +271,10 @@ public final class StringUtils {
 
     /**
      * 获取SQL PARAMS字符串
+     *
+     * @deprecated 3.5.12
      */
+    @Deprecated
     public static String sqlParam(Object obj) {
         String repStr;
         if (obj instanceof Collection) {
@@ -283,7 +290,9 @@ public final class StringUtils {
      *
      * @param obj 原字符串
      * @return 单引号包含的原字符串
+     * @deprecated 3.5.12
      */
+    @Deprecated
     public static String quotaMark(Object obj) {
         String srcStr = String.valueOf(obj);
         if (obj instanceof CharSequence) {
@@ -298,7 +307,9 @@ public final class StringUtils {
      *
      * @param coll 集合
      * @return 单引号包含的原字符串的集合形式
+     * @deprecated 3.5.12
      */
+    @Deprecated
     public static String quotaMarkList(Collection<?> coll) {
         return coll.stream().map(StringUtils::quotaMark)
             .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));

+ 50 - 17
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/TableNameParser.java

@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -59,6 +60,13 @@ public final class TableNameParser {
     private static final List<String> concerned = Arrays.asList(KEYWORD_TABLE, KEYWORD_INTO, KEYWORD_JOIN, KEYWORD_USING, KEYWORD_UPDATE, KEYWORD_STRAIGHT_JOIN);
     private static final List<String> ignored = Arrays.asList(StringPool.LEFT_BRACKET, TOKEN_SET, TOKEN_OF, TOKEN_DUAL);
 
+    /**
+     * 索引类型
+     *
+     * @since 3.5.11
+     */
+    private static final Set<String> INDEX_TYPES = new HashSet<>(Arrays.asList("UNIQUE", "FULLTEXT", "SPATIAL", "CLUSTERED", "NONCLUSTERED"));
+
     /**
      * 该表达式会匹配 SQL 中不是 SQL TOKEN 的部分,比如换行符,注释信息,结尾的 {@code ;} 等。
      * <p>
@@ -96,11 +104,16 @@ public final class TableNameParser {
         int index = 0;
         String first = tokens.get(index).getValue();
         if (isOracleSpecialDelete(first, tokens, index)) {
-            visitNameToken(tokens.get(index + 1), visitor);
+            visitNameToken(safeGetToken(index + 1), visitor);
         } else if (isCreateIndex(first, tokens, index)) {
-            visitNameToken(tokens.get(index + 4), visitor);
+            String value = tokens.get(index + 4).getValue();
+            if("ON".equalsIgnoreCase(value)) {
+                visitNameToken(safeGetToken(index + 5), visitor);
+            } else {
+                visitNameToken(safeGetToken(index + 4), visitor);
+            }
         } else if (isCreateTableIfNotExist(first, tokens, index)) {
-            visitNameToken(tokens.get(index + 5), visitor);
+            visitNameToken(safeGetToken(index + 5), visitor);
         } else {
             while (hasMoreTokens(tokens, index)) {
                 String current = tokens.get(index++).getValue();
@@ -122,6 +135,17 @@ public final class TableNameParser {
         }
     }
 
+    /**
+     * 安全访问获取SqlToken
+     *
+     * @param index 索引
+     * @return 超出索引返回 null,否则返回SqlToken
+     * @since 3.5.11
+     */
+    private SqlToken safeGetToken(int index) {
+        return index < tokens.size() ? tokens.get(index) : null;
+    }
+
     /**
      * 表名访问器
      */
@@ -173,23 +197,27 @@ public final class TableNameParser {
         return false;
     }
 
+    // CREATE INDEX temp_name_idx ON table1(name) NOLOGGING PARALLEL (DEGREE 8);
+    // CREATE FULLTEXT INDEX ft_users_content ON users(content);
     private boolean isCreateIndex(String current, List<SqlToken> tokens, int index) {
-        index++; // Point to next token
-        if (TOKEN_CREATE.equalsIgnoreCase(current) && hasIthToken(tokens, index)) {
-            String next = tokens.get(index).getValue();
+        if (TOKEN_CREATE.equalsIgnoreCase(current) && hasMoreTokens(tokens, index + 4)) {
+            String next = tokens.get(index + 1).getValue();
+            if (INDEX_TYPES.contains(next.toUpperCase())) {
+                next = tokens.get(index + 2).getValue();
+            }
             return TOKEN_INDEX.equalsIgnoreCase(next);
         }
         return false;
     }
-    
+
+    //create table if not exists `user_info`
     private boolean isCreateTableIfNotExist(String current, List<SqlToken> tokens, int index) {
-        index++; // Point to next token
-        if (TOKEN_CREATE.equalsIgnoreCase(current) && hasIthToken(tokens, index)) {
-            String tableIfNotExist = tokens.get(index).getValue();
-            tableIfNotExist += tokens.get(++index).getValue();
-            tableIfNotExist += tokens.get(++index).getValue();
-            tableIfNotExist += tokens.get(++index).getValue();
-            return "tableifnotexists".equalsIgnoreCase(tableIfNotExist);
+        if (TOKEN_CREATE.equalsIgnoreCase(current) && hasMoreTokens(tokens, index + 5)) {
+            StringBuilder tableIfNotExist = new StringBuilder();
+            for (int i = index; i <= index + 4; i++) {
+                tableIfNotExist.append(tokens.get(i).getValue());
+            }
+            return "createtableifnotexists".equalsIgnoreCase(tableIfNotExist.toString());
         }
         return false;
     }
@@ -209,6 +237,9 @@ public final class TableNameParser {
         return false;
     }
 
+    /**
+     * @deprecated 3.5.11 建议使用 {@link #hasMoreTokens(List, int)} 判断
+     */
     private static boolean hasIthToken(List<SqlToken> tokens, int currentIndex) {
         return hasMoreTokens(tokens, currentIndex) && tokens.size() > currentIndex + 3;
     }
@@ -280,9 +311,11 @@ public final class TableNameParser {
     }
 
     private static void visitNameToken(SqlToken token, TableNameVisitor visitor) {
-        String value = token.getValue().toLowerCase();
-        if (!ignored.contains(value)) {
-            visitor.visit(token);
+        if (token != null) {
+            String value = token.getValue().toLowerCase();
+            if (!ignored.contains(value)) {
+                visitor.visit(token);
+            }
         }
     }
 

+ 76 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtilsTest.java

@@ -0,0 +1,76 @@
+package com.baomidou.mybatisplus.core.toolkit;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.Environment;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.session.SqlSessionManager;
+import org.apache.ibatis.session.defaults.DefaultSqlSession;
+import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.mybatis.spring.SqlSessionTemplate;
+
+import java.util.HashMap;
+
+/**
+ * @author nieqiurong
+ */
+public class MybatisUtilsTest {
+
+    interface MyMapper {
+
+    }
+
+    @Test
+    void testGetSqlSessionFactoryByDefaultSqlSession() {
+        var configuration = getMybatisConfiguration();
+        GlobalConfigUtils.getGlobalConfig(configuration).setSqlSessionFactory(Mockito.mock(SqlSessionFactory.class));
+        var sqlSession = new DefaultSqlSession(configuration, Mockito.mock(Executor.class));
+        var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
+        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
+        Assertions.assertNotNull(sqlSessionFactory);
+    }
+
+    @Test
+    void testGetSqlSessionFactoryBySqlSessionManager() {
+        var sqlSession = SqlSessionManager.newInstance(Mockito.mock(SqlSessionFactory.class));
+        var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
+        SqlSessionFactory sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy);
+        Assertions.assertNotNull(sqlSessionFactory);
+    }
+
+    @Test
+    void testGetSqlSessionFactoryBySqlSessionTemplate() {
+        var sqlSession = new SqlSessionTemplate(getDefaultSqlSessionFactory());
+        var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
+        Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(mybatisMapperProxy));
+    }
+
+    static class MySqlSessionTemplate extends SqlSessionTemplate {
+
+        public MySqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
+            super(sqlSessionFactory);
+        }
+    }
+
+    @Test
+    void testGetSqlSessionFactoryByExtendSqlSessionTemplate() {
+        var sqlSession = new MySqlSessionTemplate(getDefaultSqlSessionFactory());
+        var mybatisMapperProxy = new MybatisMapperProxy<>(sqlSession, MyMapper.class, new HashMap<>());
+        Assertions.assertNotNull(MybatisUtils.getSqlSessionFactory(mybatisMapperProxy));
+    }
+
+    private SqlSessionFactory getDefaultSqlSessionFactory() {
+        return new DefaultSqlSessionFactory(getMybatisConfiguration());
+    }
+
+    private MybatisConfiguration getMybatisConfiguration() {
+        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration(Mockito.mock(Environment.class));
+        mybatisConfiguration.addMapper(MyMapper.class);
+        return mybatisConfiguration;
+    }
+
+}

+ 28 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/toolkit/TableNameParserTest.java

@@ -492,6 +492,34 @@ public class TableNameParserTest {
         assertThat(new TableNameParser(sql).tables()).isEqualTo(asSet("student"));
     }
 
+    @Test
+    void testCreateTableIfNotExists() {
+        var sql = """
+            CREATE TABLE IF NOT EXISTS `user_info` (
+                `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
+                `username` VARCHAR(50) NOT NULL UNIQUE,
+                `email` VARCHAR(100) NOT NULL UNIQUE,
+                `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+            """;
+        assertThat(new TableNameParser(sql).tables()).isEqualTo(asSet("`user_info`"));
+    }
+
+    @Test
+    void testCreateUniqueIndex() {
+        var sql = "CREATE UNIQUE INDEX index_name ON table1 (a, b)";
+        assertThat(new TableNameParser(sql).tables()).isEqualTo(asSet("table1"));
+        sql = "ALTER TABLE table1 ADD UNIQUE INDEX `a`(`a`)";
+        assertThat(new TableNameParser(sql).tables()).isEqualTo(asSet("table1"));
+    }
+
+    @Test
+    void testCreateFullTextIndex(){
+        var sql = "CREATE FULLTEXT INDEX index_name ON table1 (a, b)";
+        assertThat(new TableNameParser(sql).tables()).isEqualTo(asSet("table1"));
+        sql = "ALTER TABLE table1 ADD FULLTEXT INDEX `a`(`a`)";
+        assertThat(new TableNameParser(sql).tables()).isEqualTo(asSet("table1"));
+    }
 
 
     private static Collection<String> asSet(String... a) {

+ 50 - 5
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spi/CompatibleHelper.java

@@ -15,20 +15,65 @@
  */
 package com.baomidou.mybatisplus.extension.spi;
 
+import com.baomidou.mybatisplus.core.toolkit.Assert;
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
+
 import java.util.ServiceLoader;
 
 /**
  * 兼容处理辅助类
+ * <p>默认加载使用SPI实现,需要手动指定请使用{@link #setCompatibleSet(CompatibleSet)}</p>
  */
 public class CompatibleHelper {
 
-    private static CompatibleSet COMPATIBLE_SET;
+    private static final Log LOG = LogFactory.getLog(CompatibleHelper.class);
 
-    public static CompatibleSet getCompatibleSet() {
-        if (null == COMPATIBLE_SET) {
-            ServiceLoader<CompatibleSet> loader = ServiceLoader.load(CompatibleSet.class);
-            COMPATIBLE_SET = loader.iterator().next();
+    private static CompatibleSet COMPATIBLE_SET = null;
+
+    static {
+        ServiceLoader<CompatibleSet> loader = ServiceLoader.load(CompatibleSet.class, CompatibleSet.class.getClassLoader());
+        int size = 0;
+        for (CompatibleSet compatibleSet : loader) {
+            size++;
+            LOG.debug("Load compatibleSet: " + compatibleSet);
+            COMPATIBLE_SET = compatibleSet;
         }
+        if (size > 1) {
+            LOG.warn("There are currently multiple implementations, and the last one is used " + COMPATIBLE_SET);
+        }
+    }
+
+    /**
+     * 判断是否存在 {@link com.baomidou.mybatisplus.extension.spi.CompatibleSet} 实例
+     *
+     * @return 是否存在 (存在返回true,为空返回false)
+     * @since 3.5.12
+     */
+    public static boolean hasCompatibleSet() {
+        return COMPATIBLE_SET != null;
+    }
+
+    /**
+     * 手动指定 {@link com.baomidou.mybatisplus.extension.spi.CompatibleSet} 实例
+     *
+     * @param compatibleSet {@link com.baomidou.mybatisplus.extension.spi.CompatibleSet} 实例
+     * @since 3.5.12
+     */
+    public static void setCompatibleSet(CompatibleSet compatibleSet) {
+        COMPATIBLE_SET = compatibleSet;
+    }
+
+    /**
+     * 获取{@link com.baomidou.mybatisplus.extension.spi.CompatibleSet}实例
+     * <p>当为空时会抛出异常,需要检查是否为空请使用{@link #hasCompatibleSet()}</p>
+     *
+     * @return {@link com.baomidou.mybatisplus.extension.spi.CompatibleSet}
+     * @see #setCompatibleSet(CompatibleSet)
+     */
+    public static CompatibleSet getCompatibleSet() {
+        Assert.isTrue(hasCompatibleSet(), "Please add specific implementation dependencies or use the setCompatibleSet method to specify");
         return COMPATIBLE_SET;
     }
+
 }

+ 4 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spi/CompatibleSet.java

@@ -33,6 +33,10 @@ public interface CompatibleSet {
 
     boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Consumer<SqlSession> consumer);
 
+    /**
+     * @deprecated 3.5.12 无需实现
+     */
+    @Deprecated
     InputStream getInputStream(String path) throws Exception;
 
 }

+ 10 - 1
mybatis-plus-generator/build.gradle

@@ -1,3 +1,10 @@
+apply plugin: 'kotlin'
+
+compileTestKotlin {
+    kotlinOptions {
+        freeCompilerArgs = ['-Xjvm-default=all']
+    }
+}
 dependencies {
     implementation project(":mybatis-plus-spring")
     implementation "${lib.velocity}"
@@ -6,12 +13,13 @@ dependencies {
     implementation "${lib.enjoy}"
     implementation "${lib.'swagger-annotations'}"
     implementation "io.springfox:springfox-swagger2:3.0.0"
+    implementation "${lib."kotlin-stdlib-jdk8"}"
 
 
     compileOnly "org.jetbrains:annotations:24.1.0"
     testImplementation "${lib.sqlserver}"
     testImplementation "${lib.postgresql}"
-    testImplementation lib.oracle as ConfigurableFileTree
+    testImplementation "${lib.oracle}"
     testImplementation lib.dm as ConfigurableFileTree
     testImplementation "${lib.h2}"
     testImplementation "${lib.mysql}"
@@ -19,5 +27,6 @@ dependencies {
     testImplementation "${lib.firebird}"
     testImplementation "${lib.'swagger-annotations'}"
     testImplementation "${lib.'logback-classic'}"
+    testImplementation "${lib.'spring-web'}"
     testCompileOnly "org.jetbrains:annotations:24.1.0"
 }

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

@@ -91,4 +91,10 @@ public interface ConstVal {
      * @see com.baomidou.mybatisplus.core.metadata.TableInfoHelper.DEFAULT_ID_NAME
      */
     String DEFAULT_ID_NAME = "id";
+
+    /**
+     * 主键
+     * @since 3.5.12
+     */
+    String PRIMARY = "PRIMARY";
 }

+ 12 - 0
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/index/AbstractMapperMethodHandler.java

@@ -16,6 +16,7 @@
 package com.baomidou.mybatisplus.generator.index;
 
 import com.baomidou.mybatisplus.generator.IGenerateMapperMethodHandler;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
 
 /**
  * @author nieqiurong
@@ -70,4 +71,15 @@ public abstract class AbstractMapperMethodHandler implements IGenerateMapperMeth
             "    }\n";
     }
 
+    /**
+     * 判断当前索引名称是否为主键索引 (索引名为PRIMARY或PRIMARY开头的为主键索引)
+     *
+     * @param indexName 索引名称
+     * @return 是否为主键索引
+     * @since 3.5.12
+     */
+    public boolean isPrimaryKey(String indexName) {
+        return indexName.toUpperCase().startsWith(ConstVal.PRIMARY);
+    }
+
 }

+ 2 - 1
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/index/DefaultGenerateMapperLambdaMethodHandler.java

@@ -77,7 +77,8 @@ public class DefaultGenerateMapperLambdaMethodHandler extends AbstractMapperMeth
             if (this.singleIndex && indexSize > 1) {
                 continue;
             }
-            if ("PRIMARY".equals(indexName) && indexSize == 1) {
+            // use byId
+            if (indexSize == 1 && isPrimaryKey(indexName)) {
                 continue;
             }
             Map<String, TableField> tableFieldMap = tableInfo.getTableFieldMap();

+ 2 - 1
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/index/DefaultGenerateMapperMethodHandler.java

@@ -75,7 +75,8 @@ public class DefaultGenerateMapperMethodHandler extends AbstractMapperMethodHand
             if (this.singleIndex && indexSize > 1) {
                 continue;
             }
-            if ("PRIMARY".equals(indexName) && indexSize == 1) {
+            // use byId
+            if (indexSize == 1 && isPrimaryKey(indexName)) {
                 continue;
             }
             List<TableField> tableFieldList = new ArrayList<>();

+ 0 - 1
mybatis-plus-generator/src/main/resources/templates/controller.java.ej

@@ -26,7 +26,6 @@ import #(superControllerClassPackage);
 @RequestMapping("#if(package.ModuleName)/#(package.ModuleName)#end/#if(controllerMappingHyphenStyle)#(controllerMappingHyphen)#else#(table.entityPath)#end")
 #if(kotlin)
 class #(table.controllerName)#if(superControllerClass) : #(superControllerClass)()#end
-
 #else
 #if(superControllerClass)
 public class #(table.controllerName) extends #(superControllerClass) {

+ 0 - 1
mybatis-plus-generator/src/main/resources/templates/controller.java.vm

@@ -26,7 +26,6 @@ import ${superControllerClassPackage};
 @RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end")
 #if(${kotlin})
 class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end
-
 #else
 #if(${superControllerClass})
 public class ${table.controllerName} extends ${superControllerClass} {

+ 4 - 4
mybatis-plus-generator/src/main/resources/templates/entity.java.btl

@@ -107,13 +107,13 @@ public class ${entity} {
     public String toString() {
         return "${entity}{" +
     <% for(field in table.fields){ %>
-       <% if(fieldLP.index==0){ %>
-        "${field.propertyName} = " + ${field.propertyName} +
+       <% if(fieldLP.dataIndex==0){ %>
+            "${field.propertyName} = " + ${field.propertyName} +
        <% }else{ %>
-        ", ${field.propertyName} = " + ${field.propertyName} +
+            ", ${field.propertyName} = " + ${field.propertyName} +
        <% } %>
     <% } %>
-        "}";
+            "}";
     }
 <% } %>
 }

+ 3 - 3
mybatis-plus-generator/src/main/resources/templates/entity.java.ej

@@ -104,12 +104,12 @@ public class #(entity) {
         return "#(entity){" +
   #for(field : table.fields)
     #if(for.index == 0)
-        "#(field.propertyName) = " + #(field.propertyName) +
+            "#(field.propertyName) = " + #(field.propertyName) +
     #else
-        ", #(field.propertyName) = " + #(field.propertyName) +
+            ", #(field.propertyName) = " + #(field.propertyName) +
     #end
   #end
-        "}";
+            "}";
     }
 #end
 }

+ 2 - 1
mybatis-plus-generator/src/main/resources/templates/entity.java.ftl

@@ -7,6 +7,7 @@ import ${pkg};
 <#list importEntityJavaPackages as pkg>
 import ${pkg};
 </#list>
+
 /**
  * <p>
  * ${table.comment!}
@@ -106,7 +107,7 @@ public class ${entity} {
             ", ${field.propertyName} = " + ${field.propertyName} +
         </#if>
     </#list>
-        "}";
+            "}";
     }
 </#if>
 }

+ 3 - 3
mybatis-plus-generator/src/main/resources/templates/entity.java.vm

@@ -104,12 +104,12 @@ public class ${entity} {
         return "${entity}{" +
   #foreach($field in ${table.fields})
     #if($!{foreach.index}==0)
-        "${field.propertyName} = " + ${field.propertyName} +
+            "${field.propertyName} = " + ${field.propertyName} +
     #else
-        ", ${field.propertyName} = " + ${field.propertyName} +
+            ", ${field.propertyName} = " + ${field.propertyName} +
     #end
   #end
-        "}";
+            "}";
     }
 #end
 }

+ 6 - 7
mybatis-plus-generator/src/main/resources/templates/entity.kt.btl

@@ -1,11 +1,11 @@
 package ${package.Entity}
 
 <% for(pkg in importEntityFrameworkPackages){ %>
-import ${pkg};
+import ${pkg}
 <% } %>
 
 <% for(pkg in importEntityJavaPackages){ %>
-import ${pkg};
+import ${pkg}
 <% } %>
 
 /**
@@ -47,9 +47,9 @@ class ${entity} {
     ${an.displayName}
     <% } %>
     <% if(field.propertyType == 'Integer'){ %>
-    var ${field.propertyName}: Int ? = null
+    var ${field.propertyName}: Int? = null
     <% }else{ %>
-    var ${field.propertyName}: ${field.propertyType} ? = null
+    var ${field.propertyName}: ${field.propertyType}? = null
     <% } %>
 
 <% } %>
@@ -73,11 +73,10 @@ class ${entity} {
 
 <% } %>
 <% if(entityToString){ %>
-    @Override
-    override fun toString(): String  {
+    override fun toString(): String {
         return "${entity}{" +
     <% for(field in table.fields){ %>
-       <% if(fieldLP.index==0){ %>
+       <% if(fieldLP.dataIndex==0){ %>
         "${field.propertyName}=" + ${field.propertyName} +
        <% }else{ %>
         ", ${field.propertyName}=" + ${field.propertyName} +

+ 2 - 2
mybatis-plus-generator/src/main/resources/templates/entity.kt.ej

@@ -1,11 +1,11 @@
 package #(package.Entity);
 
 #for(pkg : importEntityFrameworkPackages)
-import #(pkg);
+import #(pkg)
 #end
 
 #for(pkg : importEntityJavaPackages)
-import #(pkg);
+import #(pkg)
 #end
 
 /**

+ 2 - 2
mybatis-plus-generator/src/main/resources/templates/entity.kt.vm

@@ -1,11 +1,11 @@
 package ${package.Entity};
 
 #foreach($pkg in ${importEntityFrameworkPackages})
-import ${pkg};
+import ${pkg}
 #end
 
 #foreach($pkg in ${importEntityJavaPackages})
-import ${pkg};
+import ${pkg}
 #end
 
 /**

+ 0 - 1
mybatis-plus-generator/src/main/resources/templates/mapper.java.ftl

@@ -38,4 +38,3 @@ public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
     ${m.method}
 </#list>
 }
-

+ 2 - 2
mybatis-plus-generator/src/main/resources/templates/serviceImpl.java.ej

@@ -18,11 +18,11 @@ import org.springframework.stereotype.Service;
  */
 @Service
 #if(kotlin)
-open class #(table.serviceImplName) : #(superServiceImplClass)<#(table.mapperName), #(entity)>() #if(generateService), #(table.serviceName)#end {
+open class #(table.serviceImplName) : #(superServiceImplClass)<#(table.mapperName), #(entity)>()#if(generateService), #(table.serviceName) #end{
 
 }
 #else
-public class #(table.serviceImplName) extends #(superServiceImplClass)<#(table.mapperName), #(entity)> #if(generateService) implements #(table.serviceName)#end {
+public class #(table.serviceImplName) extends #(superServiceImplClass)<#(table.mapperName), #(entity)> #if(generateService)implements #(table.serviceName) #end{
 
 }
 #end

+ 18 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/controller/SimpleController.java

@@ -0,0 +1,18 @@
+package com.baomidou.demo.beetl.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/demo.beetl/simple")
+public class SimpleController {
+
+}

+ 155 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/entity/Simple.java

@@ -0,0 +1,155 @@
+package com.baomidou.demo.beetl.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+public class Simple implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
+    /**
+     * 年龄
+     */
+    private Integer age;
+
+    /**
+     * 删除标识1
+     */
+    private Byte deleteFlag;
+
+    /**
+     * 删除标识2
+     */
+    private Byte deleted;
+
+    /**
+     * 测试布尔类型
+     */
+    private Byte isOk;
+
+    /**
+     * 版本
+     */
+    private Long version;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Byte getDeleteFlag() {
+        return deleteFlag;
+    }
+
+    public void setDeleteFlag(Byte deleteFlag) {
+        this.deleteFlag = deleteFlag;
+    }
+
+    public Byte getDeleted() {
+        return deleted;
+    }
+
+    public void setDeleted(Byte deleted) {
+        this.deleted = deleted;
+    }
+
+    public Byte getIsOk() {
+        return isOk;
+    }
+
+    public void setIsOk(Byte isOk) {
+        this.isOk = isOk;
+    }
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public String toString() {
+        return "Simple{" +
+            "id = " + id +
+            ", name = " + name +
+            ", age = " + age +
+            ", deleteFlag = " + deleteFlag +
+            ", deleted = " + deleted +
+            ", isOk = " + isOk +
+            ", version = " + version +
+            ", createTime = " + createTime +
+            ", updateTime = " + updateTime +
+            "}";
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/mapper/SimpleMapper.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.beetl.mapper;
+
+import com.baomidou.demo.beetl.entity.Simple;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface SimpleMapper extends BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.demo.beetl.mapper.SimpleMapper">
+
+</mapper>

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/service/ISimpleService.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.beetl.service;
+
+import com.baomidou.demo.beetl.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface ISimpleService extends IService<Simple> {
+
+}

+ 20 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/beetl/service/impl/SimpleServiceImpl.java

@@ -0,0 +1,20 @@
+package com.baomidou.demo.beetl.service.impl;
+
+import com.baomidou.demo.beetl.entity.Simple;
+import com.baomidou.demo.beetl.mapper.SimpleMapper;
+import com.baomidou.demo.beetl.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+public class SimpleServiceImpl extends ServiceImpl<SimpleMapper, Simple> implements ISimpleService {
+
+}

+ 18 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/controller/SimpleController.java

@@ -0,0 +1,18 @@
+package com.baomidou.demo.enjoy.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/demo.enjoy/simple")
+public class SimpleController {
+
+}

+ 155 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/entity/Simple.java

@@ -0,0 +1,155 @@
+package com.baomidou.demo.enjoy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+public class Simple implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
+    /**
+     * 年龄
+     */
+    private Integer age;
+
+    /**
+     * 删除标识1
+     */
+    private Byte deleteFlag;
+
+    /**
+     * 删除标识2
+     */
+    private Byte deleted;
+
+    /**
+     * 测试布尔类型
+     */
+    private Byte isOk;
+
+    /**
+     * 版本
+     */
+    private Long version;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Byte getDeleteFlag() {
+        return deleteFlag;
+    }
+
+    public void setDeleteFlag(Byte deleteFlag) {
+        this.deleteFlag = deleteFlag;
+    }
+
+    public Byte getDeleted() {
+        return deleted;
+    }
+
+    public void setDeleted(Byte deleted) {
+        this.deleted = deleted;
+    }
+
+    public Byte getIsOk() {
+        return isOk;
+    }
+
+    public void setIsOk(Byte isOk) {
+        this.isOk = isOk;
+    }
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public String toString() {
+        return "Simple{" +
+            "id = " + id +
+            ", name = " + name +
+            ", age = " + age +
+            ", deleteFlag = " + deleteFlag +
+            ", deleted = " + deleted +
+            ", isOk = " + isOk +
+            ", version = " + version +
+            ", createTime = " + createTime +
+            ", updateTime = " + updateTime +
+            "}";
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/mapper/SimpleMapper.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.enjoy.mapper;
+
+import com.baomidou.demo.enjoy.entity.Simple;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface SimpleMapper extends BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.demo.enjoy.mapper.SimpleMapper">
+
+</mapper>

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/service/ISimpleService.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.enjoy.service;
+
+import com.baomidou.demo.enjoy.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface ISimpleService extends IService<Simple> {
+
+}

+ 20 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/enjoy/service/impl/SimpleServiceImpl.java

@@ -0,0 +1,20 @@
+package com.baomidou.demo.enjoy.service.impl;
+
+import com.baomidou.demo.enjoy.entity.Simple;
+import com.baomidou.demo.enjoy.mapper.SimpleMapper;
+import com.baomidou.demo.enjoy.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+public class SimpleServiceImpl extends ServiceImpl<SimpleMapper, Simple> implements ISimpleService {
+
+}

+ 18 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/controller/SimpleController.java

@@ -0,0 +1,18 @@
+package com.baomidou.demo.freemarker.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/demo.freemarker/simple")
+public class SimpleController {
+
+}

+ 155 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/entity/Simple.java

@@ -0,0 +1,155 @@
+package com.baomidou.demo.freemarker.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+public class Simple implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
+    /**
+     * 年龄
+     */
+    private Integer age;
+
+    /**
+     * 删除标识1
+     */
+    private Byte deleteFlag;
+
+    /**
+     * 删除标识2
+     */
+    private Byte deleted;
+
+    /**
+     * 测试布尔类型
+     */
+    private Byte isOk;
+
+    /**
+     * 版本
+     */
+    private Long version;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Byte getDeleteFlag() {
+        return deleteFlag;
+    }
+
+    public void setDeleteFlag(Byte deleteFlag) {
+        this.deleteFlag = deleteFlag;
+    }
+
+    public Byte getDeleted() {
+        return deleted;
+    }
+
+    public void setDeleted(Byte deleted) {
+        this.deleted = deleted;
+    }
+
+    public Byte getIsOk() {
+        return isOk;
+    }
+
+    public void setIsOk(Byte isOk) {
+        this.isOk = isOk;
+    }
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public String toString() {
+        return "Simple{" +
+            "id = " + id +
+            ", name = " + name +
+            ", age = " + age +
+            ", deleteFlag = " + deleteFlag +
+            ", deleted = " + deleted +
+            ", isOk = " + isOk +
+            ", version = " + version +
+            ", createTime = " + createTime +
+            ", updateTime = " + updateTime +
+            "}";
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/mapper/SimpleMapper.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.freemarker.mapper;
+
+import com.baomidou.demo.freemarker.entity.Simple;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface SimpleMapper extends BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.demo.freemarker.mapper.SimpleMapper">
+
+</mapper>

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/service/ISimpleService.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.freemarker.service;
+
+import com.baomidou.demo.freemarker.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface ISimpleService extends IService<Simple> {
+
+}

+ 20 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/freemarker/service/impl/SimpleServiceImpl.java

@@ -0,0 +1,20 @@
+package com.baomidou.demo.freemarker.service.impl;
+
+import com.baomidou.demo.freemarker.entity.Simple;
+import com.baomidou.demo.freemarker.mapper.SimpleMapper;
+import com.baomidou.demo.freemarker.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+public class SimpleServiceImpl extends ServiceImpl<SimpleMapper, Simple> implements ISimpleService {
+
+}

+ 18 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/controller/SimpleController.java

@@ -0,0 +1,18 @@
+package com.baomidou.demo.velocity.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/demo.velocity/simple")
+public class SimpleController {
+
+}

+ 155 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/entity/Simple.java

@@ -0,0 +1,155 @@
+package com.baomidou.demo.velocity.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+public class Simple implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
+    /**
+     * 年龄
+     */
+    private Integer age;
+
+    /**
+     * 删除标识1
+     */
+    private Byte deleteFlag;
+
+    /**
+     * 删除标识2
+     */
+    private Byte deleted;
+
+    /**
+     * 测试布尔类型
+     */
+    private Byte isOk;
+
+    /**
+     * 版本
+     */
+    private Long version;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Byte getDeleteFlag() {
+        return deleteFlag;
+    }
+
+    public void setDeleteFlag(Byte deleteFlag) {
+        this.deleteFlag = deleteFlag;
+    }
+
+    public Byte getDeleted() {
+        return deleted;
+    }
+
+    public void setDeleted(Byte deleted) {
+        this.deleted = deleted;
+    }
+
+    public Byte getIsOk() {
+        return isOk;
+    }
+
+    public void setIsOk(Byte isOk) {
+        this.isOk = isOk;
+    }
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public String toString() {
+        return "Simple{" +
+            "id = " + id +
+            ", name = " + name +
+            ", age = " + age +
+            ", deleteFlag = " + deleteFlag +
+            ", deleted = " + deleted +
+            ", isOk = " + isOk +
+            ", version = " + version +
+            ", createTime = " + createTime +
+            ", updateTime = " + updateTime +
+            "}";
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/mapper/SimpleMapper.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.velocity.mapper;
+
+import com.baomidou.demo.velocity.entity.Simple;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface SimpleMapper extends BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.demo.velocity.mapper.SimpleMapper">
+
+</mapper>

+ 16 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/service/ISimpleService.java

@@ -0,0 +1,16 @@
+package com.baomidou.demo.velocity.service;
+
+import com.baomidou.demo.velocity.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+public interface ISimpleService extends IService<Simple> {
+
+}

+ 20 - 0
mybatis-plus-generator/src/test/java/com/baomidou/demo/velocity/service/impl/SimpleServiceImpl.java

@@ -0,0 +1,20 @@
+package com.baomidou.demo.velocity.service.impl;
+
+import com.baomidou.demo.velocity.entity.Simple;
+import com.baomidou.demo.velocity.mapper.SimpleMapper;
+import com.baomidou.demo.velocity.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+public class SimpleServiceImpl extends ServiceImpl<SimpleMapper, Simple> implements ISimpleService {
+
+}

+ 18 - 0
mybatis-plus-generator/src/test/java/com/baomidou/mybatisplus/generator/index/MapperMethodHandlerTest.java

@@ -0,0 +1,18 @@
+package com.baomidou.mybatisplus.generator.index;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class MapperMethodHandlerTest {
+
+    @Test
+    void testIsPrimaryKey() {
+        var method = new DefaultGenerateMapperMethodHandler();
+        Assertions.assertTrue(method.isPrimaryKey("PRIMARY"));
+        Assertions.assertTrue(method.isPrimaryKey("primary"));
+        Assertions.assertTrue(method.isPrimaryKey("PRIMARY_KEY_1"));
+        Assertions.assertTrue(method.isPrimaryKey("primary_key_1"));
+        Assertions.assertFalse(method.isPrimaryKey("id_idx"));
+    }
+
+}

+ 53 - 0
mybatis-plus-generator/src/test/java/com/baomidou/mybatisplus/generator/samples/H2CodeGeneratorTest.java

@@ -8,6 +8,11 @@ import com.baomidou.mybatisplus.generator.config.po.TableField;
 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 com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
+import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
+import com.baomidou.mybatisplus.generator.engine.EnjoyTemplateEngine;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
 import com.baomidou.mybatisplus.generator.fill.Column;
 import com.baomidou.mybatisplus.generator.fill.Property;
 import com.baomidou.mybatisplus.generator.query.DefaultQuery;
@@ -16,12 +21,18 @@ import com.baomidou.mybatisplus.generator.type.TypeRegistry;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.stream.Stream;
 
 /**
  * H2 代码生成
@@ -31,6 +42,8 @@ import java.util.Map;
  */
 public class H2CodeGeneratorTest extends BaseGeneratorTest {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(H2CodeGeneratorTest.class);
+
     /**
      * 执行初始化数据库脚本
      */
@@ -66,6 +79,46 @@ public class H2CodeGeneratorTest extends BaseGeneratorTest {
         generator.execute();
     }
 
+    static Stream<Arguments> testByTemplateEngine() {
+        return Stream.of(
+            Arguments.arguments("velocity", new VelocityTemplateEngine()),
+            Arguments.arguments("freemarker", new FreemarkerTemplateEngine()),
+            Arguments.arguments("beetl", new BeetlTemplateEngine()),
+            Arguments.arguments("enjoy", new EnjoyTemplateEngine())
+        );
+    }
+
+    @MethodSource
+    @ParameterizedTest
+    public void testByTemplateEngine(String engine, AbstractTemplateEngine templateEngine) {
+        String userDir = System.getProperty("user.dir");
+        String outputDir = userDir + File.separator + "src" + File.separator + "test" + File.separator + "java";
+        LOGGER.info("当前执行引擎:{}, 输出目录:{}", engine, outputDir);
+        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
+        generator.strategy(strategyConfig().addTablePrefix("t_")
+            .entityBuilder().enableFileOverride()
+            .mapperBuilder().enableFileOverride()
+                .controllerBuilder().enableFileOverride().serviceBuilder().enableFileOverride()
+            .build());
+        generator.packageInfo(new PackageConfig.Builder().moduleName("demo" + "." + engine).build());
+        generator.global(globalConfig().commentDate(() -> "2025-03-27").disableOpenDir().outputDir(outputDir).build());
+        generator.execute(templateEngine);
+
+        // -- 生成kotlin代码
+        LOGGER.info("当前执行引擎:{}, 执行生成Kotlin代码.", engine);
+        outputDir = userDir + File.separator + "src" + File.separator + "test" + File.separator + "kotlin";
+        generator = new AutoGenerator(DATA_SOURCE_CONFIG);
+
+        generator.strategy(strategyConfig().addTablePrefix("t_")
+            .entityBuilder().enableFileOverride().importPackageFunction(ArrayList::new)
+            .mapperBuilder().enableFileOverride().importPackageFunction(ArrayList::new)
+            .controllerBuilder().enableFileOverride().serviceBuilder().enableFileOverride()
+            .build());
+        generator.packageInfo(new PackageConfig.Builder().moduleName(engine).build());
+        generator.global(globalConfig().enableKotlin().commentDate(() -> "2025-03-27").disableOpenDir().outputDir(outputDir).build());
+        generator.execute(templateEngine);
+    }
+
     /**
      * 过滤表前缀(后缀同理,支持多个)
      * result: t_simple -> simple

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/controller/SimpleController.kt

@@ -0,0 +1,16 @@
+package com.baomidou.beetl.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/beetl/simple")
+class SimpleController

+ 80 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/entity/Simple.kt

@@ -0,0 +1,80 @@
+package com.baomidou.beetl.entity
+
+import com.baomidou.mybatisplus.annotation.TableName
+import com.baomidou.mybatisplus.annotation.IdType
+import com.baomidou.mybatisplus.annotation.TableId
+
+import java.time.LocalDateTime
+import java.io.Serializable
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+class Simple : Serializable {
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    var id: Int? = null
+
+    /**
+     * 姓名
+     */
+    var name: String? = null
+
+    /**
+     * 年龄
+     */
+    var age: Int? = null
+
+    /**
+     * 删除标识1
+     */
+    var deleteFlag: Byte? = null
+
+    /**
+     * 删除标识2
+     */
+    var deleted: Byte? = null
+
+    /**
+     * 测试布尔类型
+     */
+    var isOk: Byte? = null
+
+    /**
+     * 版本
+     */
+    var version: Long? = null
+
+    /**
+     * 创建时间
+     */
+    var createTime: LocalDateTime? = null
+
+    /**
+     * 更新时间
+     */
+    var updateTime: LocalDateTime? = null
+
+    override fun toString(): String {
+        return "Simple{" +
+        "id=" + id +
+        ", name=" + name +
+        ", age=" + age +
+        ", deleteFlag=" + deleteFlag +
+        ", deleted=" + deleted +
+        ", isOk=" + isOk +
+        ", version=" + version +
+        ", createTime=" + createTime +
+        ", updateTime=" + updateTime +
+        "}"
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/mapper/SimpleMapper.kt

@@ -0,0 +1,16 @@
+package com.baomidou.beetl.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.beetl.entity.Simple;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface SimpleMapper : BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.beetl.mapper.SimpleMapper">
+
+</mapper>

+ 14 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/service/ISimpleService.kt

@@ -0,0 +1,14 @@
+package com.baomidou.beetl.service;
+
+import com.baomidou.beetl.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface ISimpleService : IService<Simple>

+ 20 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/beetl/service/impl/SimpleServiceImpl.kt

@@ -0,0 +1,20 @@
+package com.baomidou.beetl.service.impl;
+
+import com.baomidou.beetl.entity.Simple;
+import com.baomidou.beetl.mapper.SimpleMapper;
+import com.baomidou.beetl.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+open class SimpleServiceImpl : ServiceImpl<SimpleMapper, Simple>(), ISimpleService {
+
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/controller/SimpleController.kt

@@ -0,0 +1,16 @@
+package com.baomidou.enjoy.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/enjoy/simple")
+class SimpleController

+ 80 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/entity/Simple.kt

@@ -0,0 +1,80 @@
+package com.baomidou.enjoy.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName
+import com.baomidou.mybatisplus.annotation.IdType
+import com.baomidou.mybatisplus.annotation.TableId
+
+import java.time.LocalDateTime
+import java.io.Serializable
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+class Simple : Serializable {
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    var id: Int? = null
+
+    /**
+     * 姓名
+     */
+    var name: String? = null
+
+    /**
+     * 年龄
+     */
+    var age: Int? = null
+
+    /**
+     * 删除标识1
+     */
+    var deleteFlag: Byte? = null
+
+    /**
+     * 删除标识2
+     */
+    var deleted: Byte? = null
+
+    /**
+     * 测试布尔类型
+     */
+    var isOk: Byte? = null
+
+    /**
+     * 版本
+     */
+    var version: Long? = null
+
+    /**
+     * 创建时间
+     */
+    var createTime: LocalDateTime? = null
+
+    /**
+     * 更新时间
+     */
+    var updateTime: LocalDateTime? = null
+
+    override fun toString(): String {
+        return "Simple{" +
+        "id=" + id +
+        ", name=" + name +
+        ", age=" + age +
+        ", deleteFlag=" + deleteFlag +
+        ", deleted=" + deleted +
+        ", isOk=" + isOk +
+        ", version=" + version +
+        ", createTime=" + createTime +
+        ", updateTime=" + updateTime +
+        "}"
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/mapper/SimpleMapper.kt

@@ -0,0 +1,16 @@
+package com.baomidou.enjoy.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.enjoy.entity.Simple;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface SimpleMapper : BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.enjoy.mapper.SimpleMapper">
+
+</mapper>

+ 14 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/service/ISimpleService.kt

@@ -0,0 +1,14 @@
+package com.baomidou.enjoy.service;
+
+import com.baomidou.enjoy.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface ISimpleService : IService<Simple>

+ 20 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/enjoy/service/impl/SimpleServiceImpl.kt

@@ -0,0 +1,20 @@
+package com.baomidou.enjoy.service.impl;
+
+import com.baomidou.enjoy.entity.Simple;
+import com.baomidou.enjoy.mapper.SimpleMapper;
+import com.baomidou.enjoy.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+open class SimpleServiceImpl : ServiceImpl<SimpleMapper, Simple>(), ISimpleService {
+
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/controller/SimpleController.kt

@@ -0,0 +1,16 @@
+package com.baomidou.freemarker.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/freemarker/simple")
+class SimpleController

+ 80 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/entity/Simple.kt

@@ -0,0 +1,80 @@
+package com.baomidou.freemarker.entity
+
+import com.baomidou.mybatisplus.annotation.TableName
+import com.baomidou.mybatisplus.annotation.IdType
+import com.baomidou.mybatisplus.annotation.TableId
+
+import java.time.LocalDateTime
+import java.io.Serializable
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+class Simple : Serializable {
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    var id: Int? = null
+
+    /**
+     * 姓名
+     */
+    var name: String? = null
+
+    /**
+     * 年龄
+     */
+    var age: Int? = null
+
+    /**
+     * 删除标识1
+     */
+    var deleteFlag: Byte? = null
+
+    /**
+     * 删除标识2
+     */
+    var deleted: Byte? = null
+
+    /**
+     * 测试布尔类型
+     */
+    var isOk: Byte? = null
+
+    /**
+     * 版本
+     */
+    var version: Long? = null
+
+    /**
+     * 创建时间
+     */
+    var createTime: LocalDateTime? = null
+
+    /**
+     * 更新时间
+     */
+    var updateTime: LocalDateTime? = null
+
+    override fun toString(): String {
+        return "Simple{" +
+        "id=" + id +
+        ", name=" + name +
+        ", age=" + age +
+        ", deleteFlag=" + deleteFlag +
+        ", deleted=" + deleted +
+        ", isOk=" + isOk +
+        ", version=" + version +
+        ", createTime=" + createTime +
+        ", updateTime=" + updateTime +
+        "}"
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/mapper/SimpleMapper.kt

@@ -0,0 +1,16 @@
+package com.baomidou.freemarker.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.freemarker.entity.Simple;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface SimpleMapper : BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.freemarker.mapper.SimpleMapper">
+
+</mapper>

+ 14 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/service/ISimpleService.kt

@@ -0,0 +1,14 @@
+package com.baomidou.freemarker.service;
+
+import com.baomidou.freemarker.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface ISimpleService : IService<Simple>

+ 20 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/freemarker/service/impl/SimpleServiceImpl.kt

@@ -0,0 +1,20 @@
+package com.baomidou.freemarker.service.impl;
+
+import com.baomidou.freemarker.entity.Simple;
+import com.baomidou.freemarker.mapper.SimpleMapper;
+import com.baomidou.freemarker.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+open class SimpleServiceImpl : ServiceImpl<SimpleMapper, Simple>(), ISimpleService {
+
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/controller/SimpleController.kt

@@ -0,0 +1,16 @@
+package com.baomidou.velocity.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 测试表 前端控制器
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Controller
+@RequestMapping("/velocity/simple")
+class SimpleController

+ 80 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/entity/Simple.kt

@@ -0,0 +1,80 @@
+package com.baomidou.velocity.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName
+import com.baomidou.mybatisplus.annotation.IdType
+import com.baomidou.mybatisplus.annotation.TableId
+
+import java.time.LocalDateTime
+import java.io.Serializable
+
+/**
+ * <p>
+ * 测试表
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@TableName("t_simple")
+class Simple : Serializable {
+
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    var id: Int? = null
+
+    /**
+     * 姓名
+     */
+    var name: String? = null
+
+    /**
+     * 年龄
+     */
+    var age: Int? = null
+
+    /**
+     * 删除标识1
+     */
+    var deleteFlag: Byte? = null
+
+    /**
+     * 删除标识2
+     */
+    var deleted: Byte? = null
+
+    /**
+     * 测试布尔类型
+     */
+    var isOk: Byte? = null
+
+    /**
+     * 版本
+     */
+    var version: Long? = null
+
+    /**
+     * 创建时间
+     */
+    var createTime: LocalDateTime? = null
+
+    /**
+     * 更新时间
+     */
+    var updateTime: LocalDateTime? = null
+
+    override fun toString(): String {
+        return "Simple{" +
+        "id=" + id +
+        ", name=" + name +
+        ", age=" + age +
+        ", deleteFlag=" + deleteFlag +
+        ", deleted=" + deleted +
+        ", isOk=" + isOk +
+        ", version=" + version +
+        ", createTime=" + createTime +
+        ", updateTime=" + updateTime +
+        "}"
+    }
+}

+ 16 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/mapper/SimpleMapper.kt

@@ -0,0 +1,16 @@
+package com.baomidou.velocity.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.velocity.entity.Simple;
+
+/**
+ * <p>
+ * 测试表 Mapper 接口
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface SimpleMapper : BaseMapper<Simple> {
+
+}

+ 5 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/mapper/xml/SimpleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.baomidou.velocity.mapper.SimpleMapper">
+
+</mapper>

+ 14 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/service/ISimpleService.kt

@@ -0,0 +1,14 @@
+package com.baomidou.velocity.service;
+
+import com.baomidou.velocity.entity.Simple;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 测试表 服务类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+interface ISimpleService : IService<Simple>

+ 20 - 0
mybatis-plus-generator/src/test/kotlin/com/baomidou/velocity/service/impl/SimpleServiceImpl.kt

@@ -0,0 +1,20 @@
+package com.baomidou.velocity.service.impl;
+
+import com.baomidou.velocity.entity.Simple;
+import com.baomidou.velocity.mapper.SimpleMapper;
+import com.baomidou.velocity.service.ISimpleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 测试表 服务实现类
+ * </p>
+ *
+ * @author baomidou
+ * @since 2025-03-27
+ */
+@Service
+open class SimpleServiceImpl : ServiceImpl<SimpleMapper, Simple>(), ISimpleService {
+
+}

+ 89 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/DynamicTableNameHandler.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2025, 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.extension;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
+import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.create.index.CreateIndex;
+import net.sf.jsqlparser.statement.create.view.CreateView;
+import net.sf.jsqlparser.statement.drop.Drop;
+import net.sf.jsqlparser.util.TablesNamesFinder;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 动态表名解析处理
+ * <p>1.无法保留sql注释(例如 select * from test; --这是个查询 处理完会变成 select * from test)</p>
+ * <p>2.无法保留语句分隔符;(例如 select * from test; 处理完会变成 select * from test )</p>
+ * <p>3.如果使用转义符包裹了表名需要自行处理</p>
+ * <p>4.select * from dual (不处理这个,自行忽略)</p>
+ *
+ * @author nieqiurong
+ * @since 3.5.11
+ */
+public class DynamicTableNameHandler extends TablesNamesFinder {
+
+    private final String originSql;
+
+    private final TableNameHandler tableNameHandler;
+
+    private final Set<Table> set = new HashSet<>();
+
+    public DynamicTableNameHandler(String originSql, TableNameHandler tableNameHandler) {
+        this.originSql = originSql;
+        this.tableNameHandler = tableNameHandler;
+        init(false);
+    }
+
+    @Override
+    public void visit(CreateIndex createIndex) {
+        super.visit(createIndex.getTable());
+    }
+
+    @Override
+    public void visit(Drop drop) {
+        if(StringUtils.isNotBlank(drop.getType())){
+            String type = drop.getType().toUpperCase();
+            if ("TABLE".equals(type)) {
+                 super.visit(drop);
+            }
+        }
+    }
+
+    @Override
+    public void visit(CreateView createView) {
+        super.visit(createView.getSelect());
+    }
+
+    @Override
+    protected String extractTableName(Table table) {
+        String originalTableName = table.getName();
+        if (table.getASTNode() == null) {
+            return originalTableName;
+        }
+        if (set.add(table)) {
+            String tableName = tableNameHandler.dynamicTableName(originSql, originalTableName);
+            if (StringUtils.isNotBlank(tableName)) {
+                table.setName(tableName);
+                return tableName;
+            }
+        }
+        return originalTableName;
+    }
+
+}

+ 3 - 1
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/parser/JsqlParserGlobal.java

@@ -46,8 +46,10 @@ public class JsqlParserGlobal {
      * <p>注意: 由于项目情况,机器配置等不一样因素,请自行根据情况创建指定线程池.</p>
      *
      * @see java.util.concurrent.ThreadPoolExecutor
+     * @see #setExecutorService(ExecutorService)
+     * @see #setExecutorService(ExecutorService, boolean)
      * @since 3.5.6
-     * @deprecated 3.5.11 后面不再公开此属性,请使用{@link #setExecutorService(ExecutorService)}} 或 {@link #setExecutorService(ExecutorService, boolean)}
+     * @deprecated 3.5.11 后面不再公开此属性
      */
     @Deprecated
     public static ExecutorService executorService;

+ 0 - 104
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameInnerInterceptor.java

@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2011-2025, 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.extension.plugins.inner;
-
-import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
-import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
-import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.session.ResultHandler;
-import org.apache.ibatis.session.RowBounds;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 动态表名
- *
- * @author jobob
- * @since 3.4.0
- */
-@Getter
-@Setter
-@NoArgsConstructor
-@SuppressWarnings({"rawtypes"})
-public class DynamicTableNameInnerInterceptor implements InnerInterceptor {
-    private Runnable hook;
-    /**
-     * 表名处理器,是否处理表名的情况都在该处理器中自行判断
-     */
-    private TableNameHandler tableNameHandler;
-
-    public DynamicTableNameInnerInterceptor(TableNameHandler tableNameHandler) {
-        this.tableNameHandler = tableNameHandler;
-    }
-
-    @Override
-    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
-        if (InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) return;
-        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
-        mpBs.sql(this.changeTable(mpBs.sql()));
-    }
-
-    @Override
-    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
-        PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
-        MappedStatement ms = mpSh.mappedStatement();
-        SqlCommandType sct = ms.getSqlCommandType();
-        if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
-            if (InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) {
-                return;
-            }
-            PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
-            mpBs.sql(this.changeTable(mpBs.sql()));
-        }
-    }
-
-    public String changeTable(String sql) {
-        ExceptionUtils.throwMpe(null == tableNameHandler, "Please implement TableNameHandler processing logic");
-        TableNameParser parser = new TableNameParser(sql);
-        List<TableNameParser.SqlToken> names = new ArrayList<>();
-        parser.accept(names::add);
-        StringBuilder builder = new StringBuilder();
-        int last = 0;
-        for (TableNameParser.SqlToken name : names) {
-            int start = name.getStart();
-            if (start != last) {
-                builder.append(sql, last, start);
-                builder.append(tableNameHandler.dynamicTableName(sql, name.getValue()));
-            }
-            last = name.getEnd();
-        }
-        if (last != sql.length()) {
-            builder.append(sql.substring(last));
-        }
-        if (hook != null) {
-            hook.run();
-        }
-        return builder.toString();
-    }
-}

+ 89 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptor.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2025, 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.extension.plugins.inner;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.extension.DynamicTableNameHandler;
+import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
+import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
+import lombok.Setter;
+import net.sf.jsqlparser.statement.Statement;
+import net.sf.jsqlparser.statement.UnsupportedStatement;
+
+/**
+ * 动态表处理器 (基于JsqlParser解析器)
+ * <p>默认情况下,如果JsqlParser解析不了,则调用父类的解析进行处理</p>
+ *
+ * @author nieqiurong
+ * @see DynamicTableNameHandler
+ * @since 3.5.11
+ */
+@Setter
+public class DynamicTableNameJsqlParserInnerInterceptor extends DynamicTableNameInnerInterceptor {
+
+    /**
+     * 是否忽略解析异常
+     */
+    private boolean ignoreException = false;
+
+    /**
+     * 当JsqlParser无法解析语句时是否进行调用父类继续解析处理
+     *
+     * @see com.baomidou.mybatisplus.core.toolkit.TableNameParser
+     */
+    private boolean shouldFallback = true;
+
+
+    @Deprecated
+    public DynamicTableNameJsqlParserInnerInterceptor() {
+    }
+
+    public DynamicTableNameJsqlParserInnerInterceptor(TableNameHandler tableNameHandler) {
+        super(tableNameHandler);
+    }
+
+    @Override
+    protected String processTableName(String sql) {
+        boolean unsupported = false;
+        try {
+            Statement statement = JsqlParserGlobal.parse(sql);
+            statement.accept(new DynamicTableNameHandler(sql, super.getTableNameHandler()));
+            if (statement instanceof UnsupportedStatement) {
+                unsupported = true;
+                return super.processTableName(sql);
+            }
+            return statement.toString();
+        } catch (Exception exception) {
+            return handleFallback(unsupported, sql, exception);
+        }
+    }
+
+    private String handleFallback(boolean unsupported, String sql, Exception originalException) {
+        Exception exception = originalException;
+        if (!unsupported || shouldFallback) {
+            try {
+                return super.processTableName(sql);
+            } catch (Exception e) {
+                exception = e;
+            }
+        }
+        if (ignoreException) {
+            return sql;
+        }
+        throw new MybatisPlusException("Table name processing failed : ", exception);
+    }
+
+}

+ 39 - 22
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java

@@ -232,19 +232,12 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
         //是否使用索引
         boolean useIndexFlag = false;
         if (StringUtils.isNotBlank(columnName)) {
-            String tableInfo = table.getName();
+            String tableName = table.getName();
             //表存在的索引
-            String dbName = null;
-            String tableName;
-            String[] tableArray = tableInfo.split("\\.");
-            if (tableArray.length == 1) {
-                tableName = tableArray[0];
-            } else {
-                dbName = tableArray[0];
-                tableName = tableArray[1];
-            }
+            String dbName = getPartItemValue(table, 1);
+            String catalogName = getPartItemValue(table, 2);
             columnName = SqlParserUtils.removeWrapperSymbol(columnName);
-            List<IndexInfo> indexInfos = getIndexInfos(dbName, tableName, connection);
+            List<IndexInfo> indexInfos = getIndexInfos(catalogName, dbName, tableName, connection);
             for (IndexInfo indexInfo : indexInfos) {
                 if (indexInfo.getColumnName().equalsIgnoreCase(columnName)) {
                     useIndexFlag = true;
@@ -253,10 +246,14 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             }
         }
         if (!useIndexFlag) {
-            throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table + ", columnName:" + columnName);
+            throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table.getName() + ", columnName:" + columnName);
         }
     }
 
+    private String getPartItemValue(Table table, int index) {
+        return index < table.getNameParts().size() ? table.getNameParts().get(index) : null;
+    }
+
     /**
      * 验证where条件的字段,是否有not、or等等,并且where的第一个字段,必须使用索引
      *
@@ -315,10 +312,12 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
     /**
      * 得到表的索引信息
      *
-     * @param dbName    ignore
-     * @param tableName ignore
-     * @param conn      ignore
-     * @return ignore
+     * @param dbName    数据库名
+     * @param tableName 表名
+     * @param conn      数据库连接
+     * @return 索引信息
+     * @see #getIndexInfos(String, String, String, String, Connection)
+     * @deprecated 3.5.11
      */
     public List<IndexInfo> getIndexInfos(String dbName, String tableName, Connection conn) {
         return getIndexInfos(null, dbName, tableName, conn);
@@ -327,13 +326,31 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
     /**
      * 得到表的索引信息
      *
-     * @param key       ignore
-     * @param dbName    ignore
-     * @param tableName ignore
-     * @param conn      ignore
-     * @return ignore
+     * @param key       缓存key
+     * @param dbName    数据库名
+     * @param tableName 表名
+     * @param conn      数据库连接
+     * @return 索引信息
+     * @see #getIndexInfos(String, String, String, String, Connection)
+     * @deprecated 3.5.11
      */
+    @Deprecated
     public List<IndexInfo> getIndexInfos(String key, String dbName, String tableName, Connection conn) {
+        return getIndexInfos(key, null, dbName, tableName, conn);
+    }
+
+    /**
+     * 得到表的索引信息
+     *
+     * @param key         缓存key
+     * @param catalogName catalogName
+     * @param dbName      数据库名
+     * @param tableName   表名
+     * @param conn        数据库连接
+     * @return 索引信息
+     * @since 3.5.11
+     */
+    public List<IndexInfo> getIndexInfos(String key, String catalogName, String dbName, String tableName, Connection conn) {
         List<IndexInfo> indexInfos = null;
         if (StringUtils.isNotBlank(key)) {
             indexInfos = indexInfoMap.get(key);
@@ -342,7 +359,7 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             ResultSet rs;
             try {
                 DatabaseMetaData metadata = conn.getMetaData();
-                String catalog = StringUtils.isBlank(dbName) ? conn.getCatalog() : dbName;
+                String catalog = StringUtils.isBlank(catalogName) ? conn.getCatalog() : catalogName;
                 String schema = StringUtils.isBlank(dbName) ? conn.getSchema() : dbName;
                 rs = metadata.getIndexInfo(catalog, schema, SqlParserUtils.removeWrapperSymbol(tableName), false, true);
                 indexInfos = new ArrayList<>();

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 271 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptorTest.java


+ 12 - 2
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/IllegalSQLInnerInterceptorTest.java

@@ -78,8 +78,8 @@ class IllegalSQLInnerInterceptorTest {
         Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM `T_DEMO` a INNER JOIN `T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
         Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM `T_DEMO` a INNER JOIN `test` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
 
-        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM test.`T_DEMO` a INNER JOIN test.`T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
-        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM test.`T_DEMO` a INNER JOIN test.`T_TEST` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
+        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM PUBLIC.`T_DEMO` a INNER JOIN PUBLIC.`T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
+        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM PUBLIC.`T_DEMO` a INNER JOIN PUBLIC.`T_TEST` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
 
         Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM T_DEMO a INNER JOIN `T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
         Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM T_DEMO a INNER JOIN `T_TEST` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
@@ -120,4 +120,14 @@ class IllegalSQLInnerInterceptorTest {
         Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("select count(*) from (select * from `T_DEMO` where b = (SELECT b FROM T_TEST limit 1)) a ", dataSource.getConnection()));
     }
 
+    @Test
+    void testCatalogAndSchemaName() {
+        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("select count(*) from TEST.PUBLIC.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("select count(*) from PUBLIC.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+        // 非同一模式,读不到索引的情况
+        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("select count(*) from DB.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("select count(*) from PUBLIC.DB.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+    }
+
+
 }

+ 90 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/DynamicTableNameHandler.java

@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011-2025, 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.extension;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
+import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.create.index.CreateIndex;
+import net.sf.jsqlparser.statement.create.view.CreateView;
+import net.sf.jsqlparser.statement.drop.Drop;
+import net.sf.jsqlparser.util.TablesNamesFinder;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 动态表名解析处理
+ * <p>1.无法保留sql注释(例如 select * from test; --这是个查询 处理完会变成 select * from test)</p>
+ * <p>2.无法保留语句分隔符;(例如 select * from test; 处理完会变成 select * from test )</p>
+ * <p>3.如果使用转义符包裹了表名需要自行处理</p>
+ * <p>4.select * from dual (不处理这个,自行忽略)</p>
+ *
+ * @author nieqiurong
+ * @since 3.5.11
+ */
+public class DynamicTableNameHandler extends TablesNamesFinder<Void> {
+
+    private final String originSql;
+
+    private final TableNameHandler tableNameHandler;
+
+    private final Set<Table> set = new HashSet<>();
+
+    public DynamicTableNameHandler(String originSql, TableNameHandler tableNameHandler) {
+        this.originSql = originSql;
+        this.tableNameHandler = tableNameHandler;
+        init(false);
+    }
+
+    @Override
+    public <S> Void visit(CreateIndex createIndex, S context) {
+        return this.visit(createIndex.getTable(), context);
+    }
+
+    @Override
+    public <S> Void visit(Drop drop, S context) {
+        if(StringUtils.isNotBlank(drop.getType())){
+            String type = drop.getType().toUpperCase();
+            if ("TABLE".equals(type)) {
+                return super.visit(drop, context);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public <S> Void visit(CreateView createView, S context) {
+        return super.visit(createView.getSelect(), context);
+    }
+
+    @Override
+    protected String extractTableName(Table table) {
+        String originalTableName = table.getName();
+        if (table.getASTNode() == null) {
+            return originalTableName;
+        }
+        if (set.add(table)) {
+            String tableName = tableNameHandler.dynamicTableName(originSql, originalTableName);
+            if (StringUtils.isNotBlank(tableName)) {
+                table.setName(tableName);
+                return tableName;
+            }
+        }
+        return originalTableName;
+    }
+
+}

+ 3 - 1
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/parser/JsqlParserGlobal.java

@@ -46,8 +46,10 @@ public class JsqlParserGlobal {
      * <p>注意: 由于项目情况,机器配置等不一样因素,请自行根据情况创建指定线程池.</p>
      *
      * @see java.util.concurrent.ThreadPoolExecutor
+     * @see #setExecutorService(ExecutorService)
+     * @see #setExecutorService(ExecutorService, boolean)
      * @since 3.5.6
-     * @deprecated 3.5.11 后面不再公开此属性,请使用{@link #setExecutorService(ExecutorService)}} 或 {@link #setExecutorService(ExecutorService, boolean)}
+     * @deprecated 3.5.11 后面不再公开此属性
      */
     @Deprecated
     public static ExecutorService executorService;

+ 89 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptor.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2025, 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.extension.plugins.inner;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.extension.DynamicTableNameHandler;
+import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
+import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
+import lombok.Setter;
+import net.sf.jsqlparser.statement.Statement;
+import net.sf.jsqlparser.statement.UnsupportedStatement;
+
+/**
+ * 动态表处理器 (基于JsqlParser解析器)
+ * <p>默认情况下,如果JsqlParser解析不了,则调用父类的解析进行处理</p>
+ *
+ * @author nieqiurong
+ * @see DynamicTableNameHandler
+ * @since 3.5.11
+ */
+@Setter
+public class DynamicTableNameJsqlParserInnerInterceptor extends DynamicTableNameInnerInterceptor {
+
+    /**
+     * 是否忽略解析异常
+     */
+    private boolean ignoreException = false;
+
+    /**
+     * 当JsqlParser无法解析语句时是否进行调用父类继续解析处理
+     *
+     * @see com.baomidou.mybatisplus.core.toolkit.TableNameParser
+     */
+    private boolean shouldFallback = true;
+
+
+    @Deprecated
+    public DynamicTableNameJsqlParserInnerInterceptor() {
+    }
+
+    public DynamicTableNameJsqlParserInnerInterceptor(TableNameHandler tableNameHandler) {
+        super(tableNameHandler);
+    }
+
+    @Override
+    protected String processTableName(String sql) {
+        boolean unsupported = false;
+        try {
+            Statement statement = JsqlParserGlobal.parse(sql);
+            statement.accept(new DynamicTableNameHandler(sql, super.getTableNameHandler()));
+            if (statement instanceof UnsupportedStatement) {
+                unsupported = true;
+                return super.processTableName(sql);
+            }
+            return statement.toString();
+        } catch (Exception exception) {
+            return handleFallback(unsupported, sql, exception);
+        }
+    }
+
+    private String handleFallback(boolean unsupported, String sql, Exception originalException) {
+        Exception exception = originalException;
+        if (!unsupported || shouldFallback) {
+            try {
+                return super.processTableName(sql);
+            } catch (Exception e) {
+                exception = e;
+            }
+        }
+        if (ignoreException) {
+            return sql;
+        }
+        throw new MybatisPlusException("Table name processing failed : ", exception);
+    }
+
+}

+ 24 - 25
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java

@@ -231,19 +231,12 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
         //是否使用索引
         boolean useIndexFlag = false;
         if (StringUtils.isNotBlank(columnName)) {
-            String tableInfo = table.getName();
             //表存在的索引
-            String dbName = null;
-            String tableName;
-            String[] tableArray = tableInfo.split("\\.");
-            if (tableArray.length == 1) {
-                tableName = tableArray[0];
-            } else {
-                dbName = tableArray[0];
-                tableName = tableArray[1];
-            }
+            String dbName = table.getSchemaName();
+            String tableName = table.getName();
+            String catalogName = table.getCatalogName();
             columnName = SqlParserUtils.removeWrapperSymbol(columnName);
-            List<IndexInfo> indexInfos = getIndexInfos(dbName, tableName, connection);
+            List<IndexInfo> indexInfos = getIndexInfos(catalogName, dbName, tableName, connection);
             for (IndexInfo indexInfo : indexInfos) {
                 if (indexInfo.getColumnName().equalsIgnoreCase(columnName)) {
                     useIndexFlag = true;
@@ -252,7 +245,7 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             }
         }
         if (!useIndexFlag) {
-            throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table + ", columnName:" + columnName);
+            throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table.getName() + ", columnName:" + columnName);
         }
     }
 
@@ -314,25 +307,31 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
     /**
      * 得到表的索引信息
      *
-     * @param dbName    ignore
-     * @param tableName ignore
-     * @param conn      ignore
-     * @return ignore
+     * @param key       缓存key
+     * @param dbName    数据库名
+     * @param tableName 表名
+     * @param conn      数据库连接
+     * @return 索引信息
+     * @see #getIndexInfos(String, String, String, String, Connection)
+     * @deprecated 3.5.11
      */
-    public List<IndexInfo> getIndexInfos(String dbName, String tableName, Connection conn) {
-        return getIndexInfos(null, dbName, tableName, conn);
+    @Deprecated
+    public List<IndexInfo> getIndexInfos(String key, String dbName, String tableName, Connection conn) {
+        return getIndexInfos(key, null, dbName, tableName, conn);
     }
 
     /**
      * 得到表的索引信息
      *
-     * @param key       ignore
-     * @param dbName    ignore
-     * @param tableName ignore
-     * @param conn      ignore
-     * @return ignore
+     * @param key         缓存key
+     * @param catalogName catalogName
+     * @param dbName      数据库名
+     * @param tableName   表名
+     * @param conn        数据库连接
+     * @return 索引信息
+     * @since 3.5.11
      */
-    public List<IndexInfo> getIndexInfos(String key, String dbName, String tableName, Connection conn) {
+    public List<IndexInfo> getIndexInfos(String key, String catalogName, String dbName, String tableName, Connection conn) {
         List<IndexInfo> indexInfos = null;
         if (StringUtils.isNotBlank(key)) {
             indexInfos = indexInfoMap.get(key);
@@ -341,7 +340,7 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             ResultSet rs;
             try {
                 DatabaseMetaData metadata = conn.getMetaData();
-                String catalog = StringUtils.isBlank(dbName) ? conn.getCatalog() : dbName;
+                String catalog = StringUtils.isBlank(catalogName) ? conn.getCatalog() : catalogName;
                 String schema = StringUtils.isBlank(dbName) ? conn.getSchema() : dbName;
                 rs = metadata.getIndexInfo(catalog, schema, SqlParserUtils.removeWrapperSymbol(tableName), false, true);
                 indexInfos = new ArrayList<>();

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 272 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptorTest.java


+ 13 - 2
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-5.0/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/IllegalSQLInnerInterceptorTest.java

@@ -78,8 +78,8 @@ class IllegalSQLInnerInterceptorTest {
         Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM `T_DEMO` a INNER JOIN `T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
         Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM `T_DEMO` a INNER JOIN `test` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
 
-        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM test.`T_DEMO` a INNER JOIN test.`T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
-        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM test.`T_DEMO` a INNER JOIN test.`T_TEST` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
+        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM PUBLIC.`T_DEMO` a INNER JOIN PUBLIC.`T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
+        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM PUBLIC.`T_DEMO` a INNER JOIN PUBLIC.`T_TEST` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
 
         Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("SELECT * FROM T_DEMO a INNER JOIN `T_TEST` b ON a.a = b.a WHERE a.a = 1", dataSource.getConnection()));
         Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("SELECT * FROM T_DEMO a INNER JOIN `T_TEST` b ON a.a = b.a WHERE a.b = 1", dataSource.getConnection()));
@@ -120,4 +120,15 @@ class IllegalSQLInnerInterceptorTest {
         Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("select count(*) from (select * from `T_DEMO` where b = (SELECT b FROM T_TEST limit 1)) a ", dataSource.getConnection()));
     }
 
+
+    @Test
+    void testCatalogAndSchemaName() {
+        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("select count(*) from TEST.PUBLIC.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+        Assertions.assertDoesNotThrow(() -> interceptor.parserSingle("select count(*) from PUBLIC.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+        // 非同一模式,读不到索引的情况
+        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("select count(*) from DB.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+        Assertions.assertThrows(MybatisPlusException.class, () -> interceptor.parserSingle("select count(*) from PUBLIC.DB.T_DEMO where a = 1 and `b` = 2", dataSource.getConnection()));
+    }
+
+
 }

+ 25 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/DynamicTableNameHandler.java

@@ -18,6 +18,9 @@ package com.baomidou.mybatisplus.extension;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
 import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.create.index.CreateIndex;
+import net.sf.jsqlparser.statement.create.view.CreateView;
+import net.sf.jsqlparser.statement.drop.Drop;
 import net.sf.jsqlparser.util.TablesNamesFinder;
 
 import java.util.HashSet;
@@ -28,6 +31,7 @@ import java.util.Set;
  * <p>1.无法保留sql注释(例如 select * from test; --这是个查询 处理完会变成 select * from test)</p>
  * <p>2.无法保留语句分隔符;(例如 select * from test; 处理完会变成 select * from test )</p>
  * <p>3.如果使用转义符包裹了表名需要自行处理</p>
+ * <p>4.select * from dual (不处理这个,自行忽略)</p>
  *
  * @author nieqiurong
  * @since 3.5.11
@@ -46,6 +50,27 @@ public class DynamicTableNameHandler extends TablesNamesFinder<Void> {
         init(false);
     }
 
+    @Override
+    public <S> Void visit(CreateIndex createIndex, S context) {
+        return this.visit(createIndex.getTable(), context);
+    }
+
+    @Override
+    public <S> Void visit(CreateView create, S context) {
+        return this.visit(create.getSelect(), context);
+    }
+
+    @Override
+    public <S> Void visit(Drop drop, S context) {
+        if(StringUtils.isNotBlank(drop.getType())){
+            String type = drop.getType().toUpperCase();
+            if ("TABLE".equals(type)) {
+                return super.visit(drop, context);
+            }
+        }
+        return null;
+    }
+
     @Override
     protected String extractTableName(Table table) {
         String originalTableName = table.getName();

+ 3 - 1
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/parser/JsqlParserGlobal.java

@@ -46,8 +46,10 @@ public class JsqlParserGlobal {
      * <p>注意: 由于项目情况,机器配置等不一样因素,请自行根据情况创建指定线程池.</p>
      *
      * @see java.util.concurrent.ThreadPoolExecutor
+     * @see #setExecutorService(ExecutorService)
+     * @see #setExecutorService(ExecutorService, boolean)
      * @since 3.5.6
-     * @deprecated 3.5.11 后面不再公开此属性,请使用{@link #setExecutorService(ExecutorService)}} 或 {@link #setExecutorService(ExecutorService, boolean)}
+     * @deprecated 3.5.11 后面不再公开此属性
      */
     @Deprecated
     public static ExecutorService executorService;

+ 12 - 24
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptor.java

@@ -21,13 +21,11 @@ import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
 import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
 import lombok.Setter;
 import net.sf.jsqlparser.statement.Statement;
-import org.apache.ibatis.logging.Log;
-import org.apache.ibatis.logging.LogFactory;
+import net.sf.jsqlparser.statement.UnsupportedStatement;
 
 /**
  * 动态表处理器 (基于JsqlParser解析器)
  * <p>默认情况下,如果JsqlParser解析不了,则调用父类的解析进行处理</p>
- * <p>默认情况下,如果无法处理此sql语句将忽略异常打印日志继续执行</p>
  *
  * @author nieqiurong
  * @see DynamicTableNameHandler
@@ -36,11 +34,6 @@ import org.apache.ibatis.logging.LogFactory;
 @Setter
 public class DynamicTableNameJsqlParserInnerInterceptor extends DynamicTableNameInnerInterceptor {
 
-    /**
-     * 日志实例
-     */
-    private static final Log LOG = LogFactory.getLog(DynamicTableNameJsqlParserInnerInterceptor.class);
-
     /**
      * 是否忽略解析异常
      */
@@ -53,10 +46,6 @@ public class DynamicTableNameJsqlParserInnerInterceptor extends DynamicTableName
      */
     private boolean shouldFallback = true;
 
-    /**
-     * 是否打印解析错误日志
-     */
-    private boolean printlnErrorLog = true;
 
     @Deprecated
     public DynamicTableNameJsqlParserInnerInterceptor() {
@@ -68,34 +57,33 @@ public class DynamicTableNameJsqlParserInnerInterceptor extends DynamicTableName
 
     @Override
     protected String processTableName(String sql) {
+        boolean unsupported = false;
         try {
             Statement statement = JsqlParserGlobal.parse(sql);
             statement.accept(new DynamicTableNameHandler(sql, super.getTableNameHandler()));
+            if (statement instanceof UnsupportedStatement) {
+                unsupported = true;
+                return super.processTableName(sql);
+            }
             return statement.toString();
         } catch (Exception exception) {
-            printlnErrorLog("Ignoring table name processing exception: " + exception.getMessage());
-            return handleFallback(sql, exception);
-        }
-    }
-
-    protected void printlnErrorLog(String log) {
-        if (printlnErrorLog) {
-            LOG.error(log);
+            return handleFallback(unsupported, sql, exception);
         }
     }
 
-    private String handleFallback(String sql, Exception originalException) {
-        if (shouldFallback) {
+    private String handleFallback(boolean unsupported, String sql, Exception originalException) {
+        Exception exception = originalException;
+        if (!unsupported || shouldFallback) {
             try {
                 return super.processTableName(sql);
             } catch (Exception e) {
-                printlnErrorLog("Fallback to parent process failed, ignoring exception : " + e.getMessage());
+                exception = e;
             }
         }
         if (ignoreException) {
             return sql;
         }
-        throw new MybatisPlusException("Table name processing failed and fallback not allowed", originalException);
+        throw new MybatisPlusException("Table name processing failed : ", exception);
     }
 
 }

+ 34 - 12
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java

@@ -234,8 +234,9 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             //表存在的索引
             String dbName = table.getSchemaName();
             String tableName = table.getName();
+            String catalogName = table.getCatalogName();
             columnName = SqlParserUtils.removeWrapperSymbol(columnName);
-            List<IndexInfo> indexInfos = getIndexInfos(dbName, tableName, connection);
+            List<IndexInfo> indexInfos = getIndexInfos(null, catalogName, dbName, tableName, connection);
             for (IndexInfo indexInfo : indexInfos) {
                 if (indexInfo.getColumnName().equalsIgnoreCase(columnName)) {
                     useIndexFlag = true;
@@ -244,7 +245,7 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             }
         }
         if (!useIndexFlag) {
-            throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table + ", columnName:" + columnName);
+            throw new MybatisPlusException("非法SQL,SQL未使用到索引, table:" + table.getName() + ", columnName:" + columnName);
         }
     }
 
@@ -306,11 +307,14 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
     /**
      * 得到表的索引信息
      *
-     * @param dbName    ignore
-     * @param tableName ignore
-     * @param conn      ignore
-     * @return ignore
+     * @param dbName    数据库名
+     * @param tableName 表名
+     * @param conn      数据库连接
+     * @return 索引信息
+     * @see #getIndexInfos(String, String, String, String, Connection)
+     * @deprecated 3.5.11
      */
+    @Deprecated
     public List<IndexInfo> getIndexInfos(String dbName, String tableName, Connection conn) {
         return getIndexInfos(null, dbName, tableName, conn);
     }
@@ -318,13 +322,31 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
     /**
      * 得到表的索引信息
      *
-     * @param key       ignore
-     * @param dbName    ignore
-     * @param tableName ignore
-     * @param conn      ignore
-     * @return ignore
+     * @param key       缓存key
+     * @param dbName    数据库名
+     * @param tableName 表名
+     * @param conn      数据库连接
+     * @return 索引信息
+     * @see #getIndexInfos(String, String, String, String, Connection)
+     * @deprecated 3.5.11
      */
+    @Deprecated
     public List<IndexInfo> getIndexInfos(String key, String dbName, String tableName, Connection conn) {
+        return getIndexInfos(key, null, dbName, tableName, conn);
+    }
+
+    /**
+     * 得到表的索引信息
+     *
+     * @param key         缓存key
+     * @param catalogName catalogName
+     * @param dbName      数据库名
+     * @param tableName   表名
+     * @param conn        数据库连接
+     * @return 索引信息
+     * @since 3.5.11
+     */
+    public List<IndexInfo> getIndexInfos(String key, String catalogName, String dbName, String tableName, Connection conn) {
         List<IndexInfo> indexInfos = null;
         if (StringUtils.isNotBlank(key)) {
             indexInfos = indexInfoMap.get(key);
@@ -333,7 +355,7 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
             ResultSet rs;
             try {
                 DatabaseMetaData metadata = conn.getMetaData();
-                String catalog = StringUtils.isBlank(dbName) ? conn.getCatalog() : dbName;
+                String catalog = StringUtils.isBlank(catalogName) ? conn.getCatalog() : catalogName;
                 String schema = StringUtils.isBlank(dbName) ? conn.getSchema() : dbName;
                 rs = metadata.getIndexInfo(catalog, schema, SqlParserUtils.removeWrapperSymbol(tableName), false, true);
                 indexInfos = new ArrayList<>();

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 239 - 0
mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser/src/test/java/com/baomidou/mybatisplus/test/extension/plugins/inner/DynamicTableNameJsqlParserInnerInterceptorTest.java


Vissa filer visades inte eftersom för många filer har ändrats