Просмотр исходного кода

Merge branch 'github3.0' into 3.0

# Conflicts:
#	CHANGELOG.md
#	changelog-temp.md
#	gradle.properties
hubin 1 год назад
Родитель
Сommit
7493bd3dff
50 измененных файлов с 1367 добавлено и 140 удалено
  1. 3 0
      CHANGELOG.md
  2. 5 5
      build.gradle
  3. 1 0
      changelog-temp.md
  4. 1 1
      gradle.properties
  5. 1 1
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractWrapper.java
  6. 100 25
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Compare.java
  7. 254 71
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Func.java
  8. 40 7
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Join.java
  9. 28 4
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Nested.java
  10. 19 5
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/query/Query.java
  11. 25 8
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/update/Update.java
  12. 1 1
      mybatis-plus-extension/build.gradle
  13. 17 4
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java
  14. 27 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/AopUtils.java
  15. 1 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DB2TypeConvert.java
  16. 0 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/DmTypeConvert.java
  17. 1 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/FirebirdTypeConvert.java
  18. 1 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/MySqlTypeConvert.java
  19. 1 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/PostgreSqlTypeConvert.java
  20. 1 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqlServerTypeConvert.java
  21. 2 1
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqliteTypeConvert.java
  22. 2 1
      mybatis-plus/build.gradle
  23. 34 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AopConfig1.java
  24. 26 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AopConfig2.java
  25. 41 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AppConfig.java
  26. 44 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/MultiAopTest.java
  27. 45 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/NoAopTest.java
  28. 44 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/SingleAopTest.java
  29. 15 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/entity/Demo.java
  30. 13 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/mapper/DemoMapper.java
  31. 11 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/service/IDemoService.java
  32. 15 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/service/impl/DemoServiceImpl.java
  33. 40 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/AppConfig.java
  34. 43 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/AppConfigWithMapperScan.java
  35. 44 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/RepositoryDefaultScanTest.java
  36. 44 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/RepositoryMapperScanTest.java
  37. 15 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/entity/Demo.java
  38. 13 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/mapper/DemoRepositoryMapper.java
  39. 11 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/service/IDemoRepositoryService.java
  40. 15 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/service/impl/DemoRepositoryServiceImpl.java
  41. 88 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/AppConfig.java
  42. 67 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/MultiSqlSessionFactoryTest.java
  43. 24 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/entity/AEntity.java
  44. 13 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/mapper/AEntityMapper.java
  45. 15 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/service/AEntityService.java
  46. 32 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/service/impl/AEntityServiceImpl.java
  47. 24 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/entity/BEntity.java
  48. 13 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/mapper/BEntityMapper.java
  49. 15 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/service/BEntityService.java
  50. 32 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/service/impl/BEntityServiceImpl.java

+ 3 - 0
CHANGELOG.md

@@ -1,5 +1,8 @@
 # CHANGELOG
 
+## [v3.5.4.1] 2023.11.4
+- fix: 修复Aop增强Mapper层导致的转换错误.
+
 ## [v3.5.4] 2023.10.22
 
 - fix: 修复Insert无字段时执行SQL报错.

+ 5 - 5
build.gradle

@@ -17,7 +17,7 @@ ext {
         mybatisSpringBootStarterVersion = '2.3.1',
         springVersion = '5.3.27',
         springBootVersion = '2.7.15',
-        springBoot3Version = '3.1.3',
+        springBoot3Version = '3.1.5',
         springCloudVersion = '3.1.1',
         jsqlparserVersion = '4.6',
         junitVersion = '5.9.0',
@@ -38,7 +38,7 @@ ext {
         "spring-tx"                  : "org.springframework:spring-tx:${springVersion}",
         "spring-web"                 : "org.springframework:spring-web:${springVersion}",
         "spring-aop"                 : "org.springframework:spring-aop:${springVersion}",
-        "aspectjrt"                  : "org.aspectj:aspectjrt:1.9.20.1",
+        "aspectjweaver"                  : "org.aspectj:aspectjweaver:1.9.20.1",
         "cglib"                      : "cglib:cglib:3.3.0",
         "imadcn"                     : "com.imadcn.framework:idworker:1.5.0",
         "spring-cloud-commons"       : "org.springframework.cloud:spring-cloud-commons:${springCloudVersion}",
@@ -74,9 +74,9 @@ ext {
         //code generator
         "velocity"            : "org.apache.velocity:velocity-engine-core:2.3",
         "freemarker"          : "org.freemarker:freemarker:2.3.32",
-        "beetl"               : "com.ibeetl:beetl:3.7.0.RELEASE",
+        "beetl"               : "com.ibeetl:beetl:3.15.10.RELEASE",
         "swagger-annotations" : "io.swagger:swagger-annotations:1.6.11",
-        "enjoy"               : "com.jfinal:enjoy:5.0.0",
+        "enjoy"               : "com.jfinal:enjoy:5.1.3",
         "logback-classic"     : "ch.qos.logback:logback-classic:1.4.11",
     ]
 }
@@ -111,7 +111,7 @@ subprojects {
     dependencies {
         testImplementation "${lib["assertj-core"]}"
         testImplementation "${lib["junit-jupiter"]}"
-        testImplementation "org.mockito:mockito-junit-jupiter:4.6.1"
+        testImplementation "org.mockito:mockito-junit-jupiter:5.6.0"
         testImplementation "${lib["lagarto"]}"
     }
 

+ 1 - 0
changelog-temp.md

@@ -0,0 +1 @@
+

+ 1 - 1
gradle.properties

@@ -1,4 +1,4 @@
-APP_VERSION=3.5.4
+APP_VERSION=3.5.4.1
 APP_GROUP=com.baomidou
 signing.keyId=1FD337F9
 signing.password=243194995

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

@@ -47,7 +47,7 @@ import static java.util.stream.Collectors.joining;
  * @author hubin miemie HCL
  * @since 2017-05-26
  */
-@SuppressWarnings({"unchecked", "serial"})
+@SuppressWarnings({"unchecked"})
 public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
     implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {
 

+ 100 - 25
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Compare.java

@@ -29,14 +29,21 @@ import java.util.function.BiPredicate;
 public interface Compare<Children, R> extends Serializable {
 
     /**
-     * ignore
+     * map 所有非空属性等于 =
+     *
+     * @param params map 类型的参数, key 是字段名, value 是字段值
+     * @return children
      */
     default <V> Children allEq(Map<R, V> params) {
         return allEq(params, true);
     }
 
     /**
-     * ignore
+     * map 所有非空属性等于 =
+     *
+     * @param params      map 类型的参数, key 是字段名, value 是字段值
+     * @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段
+     * @return children
      */
     default <V> Children allEq(Map<R, V> params, boolean null2IsNull) {
         return allEq(true, params, null2IsNull);
@@ -47,20 +54,29 @@ public interface Compare<Children, R> extends Serializable {
      *
      * @param condition   执行条件
      * @param params      map 类型的参数, key 是字段名, value 是字段值
-     * @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段\
+     * @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段
      * @return children
      */
     <V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull);
 
     /**
-     * ignore
+     * 字段过滤接口,传入多参数时允许对参数进行过滤
+     *
+     * @param filter 返回 true 来允许字段传入比对条件中
+     * @param params map 类型的参数, key 是字段名, value 是字段值
+     * @return children
      */
     default <V> Children allEq(BiPredicate<R, V> filter, Map<R, V> params) {
         return allEq(filter, params, true);
     }
 
     /**
-     * ignore
+     * 字段过滤接口,传入多参数时允许对参数进行过滤
+     *
+     * @param filter      返回 true 来允许字段传入比对条件中
+     * @param params      map 类型的参数, key 是字段名, value 是字段值
+     * @param null2IsNull 是否参数为 null 自动执行 isNull 方法, false 则忽略这个字段
+     * @return children
      */
     default <V> Children allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
         return allEq(true, filter, params, null2IsNull);
@@ -78,7 +94,11 @@ public interface Compare<Children, R> extends Serializable {
     <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull);
 
     /**
-     * ignore
+     * 等于 =
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children eq(R column, Object val) {
         return eq(true, column, val);
@@ -95,7 +115,11 @@ public interface Compare<Children, R> extends Serializable {
     Children eq(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * 不等于 &lt;&gt;
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children ne(R column, Object val) {
         return ne(true, column, val);
@@ -112,7 +136,11 @@ public interface Compare<Children, R> extends Serializable {
     Children ne(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * 大于 &gt;
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children gt(R column, Object val) {
         return gt(true, column, val);
@@ -129,7 +157,11 @@ public interface Compare<Children, R> extends Serializable {
     Children gt(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * 大于等于 &gt;=
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children ge(R column, Object val) {
         return ge(true, column, val);
@@ -146,7 +178,11 @@ public interface Compare<Children, R> extends Serializable {
     Children ge(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * 小于 &lt;
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children lt(R column, Object val) {
         return lt(true, column, val);
@@ -163,7 +199,11 @@ public interface Compare<Children, R> extends Serializable {
     Children lt(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * 小于等于 &lt;=
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children le(R column, Object val) {
         return le(true, column, val);
@@ -179,8 +219,14 @@ public interface Compare<Children, R> extends Serializable {
      */
     Children le(boolean condition, R column, Object val);
 
+
     /**
-     * ignore
+     * BETWEEN 值1 AND 值2
+     *
+     * @param column    字段
+     * @param val1      值1
+     * @param val2      值2
+     * @return children
      */
     default Children between(R column, Object val1, Object val2) {
         return between(true, column, val1, val2);
@@ -198,7 +244,12 @@ public interface Compare<Children, R> extends Serializable {
     Children between(boolean condition, R column, Object val1, Object val2);
 
     /**
-     * ignore
+     * NOT BETWEEN 值1 AND 值2
+     *
+     * @param column    字段
+     * @param val1      值1
+     * @param val2      值2
+     * @return children
      */
     default Children notBetween(R column, Object val1, Object val2) {
         return notBetween(true, column, val1, val2);
@@ -216,7 +267,11 @@ public interface Compare<Children, R> extends Serializable {
     Children notBetween(boolean condition, R column, Object val1, Object val2);
 
     /**
-     * ignore
+     * LIKE '%值%'
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children like(R column, Object val) {
         return like(true, column, val);
@@ -233,7 +288,11 @@ public interface Compare<Children, R> extends Serializable {
     Children like(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * NOT LIKE '%值%'
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children notLike(R column, Object val) {
         return notLike(true, column, val);
@@ -250,7 +309,11 @@ public interface Compare<Children, R> extends Serializable {
     Children notLike(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * NOT LIKE '%值'
+     *
+     * @param column 字段
+     * @param val    值
+     * @return children
      */
     default Children notLikeLeft(R column, Object val) {
         return notLikeLeft(true, column, val);
@@ -259,15 +322,19 @@ public interface Compare<Children, R> extends Serializable {
     /**
      * NOT LIKE '%值'
      *
-     * @param condition
-     * @param column
-     * @param val
+     * @param condition 执行条件
+     * @param column    字段
+     * @param val
      * @return children
      */
     Children notLikeLeft(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * NOT LIKE '值%'
+     *
+     * @param column 字段
+     * @param val 值
+     * @return children
      */
     default Children notLikeRight(R column, Object val) {
         return notLikeRight(true, column, val);
@@ -276,15 +343,19 @@ public interface Compare<Children, R> extends Serializable {
     /**
      * NOT LIKE '值%'
      *
-     * @param condition
-     * @param column
-     * @param val
+     * @param condition 执行条件
+     * @param column 字段
+     * @param val
      * @return children
      */
     Children notLikeRight(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * LIKE '%值'
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children likeLeft(R column, Object val) {
         return likeLeft(true, column, val);
@@ -301,7 +372,11 @@ public interface Compare<Children, R> extends Serializable {
     Children likeLeft(boolean condition, R column, Object val);
 
     /**
-     * ignore
+     * LIKE '值%'
+     *
+     * @param column    字段
+     * @param val       值
+     * @return children
      */
     default Children likeRight(R column, Object val) {
         return likeRight(true, column, val);

+ 254 - 71
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Func.java

@@ -32,7 +32,11 @@ import java.util.function.Consumer;
 public interface Func<Children, R> extends Serializable {
 
     /**
-     * ignore
+     * 字段 IS NULL
+     * <p>例: isNull("name")</p>
+     *
+     * @param column    字段
+     * @return children
      */
     default Children isNull(R column) {
         return isNull(true, column);
@@ -40,7 +44,7 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 字段 IS NULL
-     * <p>例: isNull("name")</p>
+     * <p>例: isNull(true, "name")</p>
      *
      * @param condition 执行条件
      * @param column    字段
@@ -49,7 +53,11 @@ public interface Func<Children, R> extends Serializable {
     Children isNull(boolean condition, R column);
 
     /**
-     * ignore
+     * 字段 IS NOT NULL
+     * <p>例: isNotNull("name")</p>
+     *
+     * @param column    字段
+     * @return children
      */
     default Children isNotNull(R column) {
         return isNotNull(true, column);
@@ -57,7 +65,7 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 字段 IS NOT NULL
-     * <p>例: isNotNull("name")</p>
+     * <p>例: isNotNull(true, "name")</p>
      *
      * @param condition 执行条件
      * @param column    字段
@@ -66,7 +74,15 @@ public interface Func<Children, R> extends Serializable {
     Children isNotNull(boolean condition, R column);
 
     /**
-     * ignore
+     * 字段 IN (value.get(0), value.get(1), ...)
+     * <p>例: in("id", Arrays.asList(1, 2, 3, 4, 5))</p>
+     *
+     * <li> 注意!当集合为 空或null 时, sql会拼接为:WHERE (字段名 IN ()), 执行时报错</li>
+     * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
+     *
+     * @param column    字段
+     * @param coll      数据集合
+     * @return children
      */
     default Children in(R column, Collection<?> coll) {
         return in(true, column, coll);
@@ -74,7 +90,7 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 字段 IN (value.get(0), value.get(1), ...)
-     * <p>例: in("id", Arrays.asList(1, 2, 3, 4, 5))</p>
+     * <p>例: in(true, "id", Arrays.asList(1, 2, 3, 4, 5))</p>
      *
      * <li> 注意!当集合为 空或null 时, sql会拼接为:WHERE (字段名 IN ()), 执行时报错</li>
      * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
@@ -87,7 +103,15 @@ public interface Func<Children, R> extends Serializable {
     Children in(boolean condition, R column, Collection<?> coll);
 
     /**
-     * ignore
+     * 字段 IN (v0, v1, ...)
+     * <p>例: in("id", 1, 2, 3, 4, 5)</p>
+     *
+     * <li> 注意!当数组为 空或null 时, sql会拼接为:WHERE (字段名 IN ()), 执行时报错</li>
+     * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
+     *
+     * @param column    字段
+     * @param values    数据数组
+     * @return children
      */
     default Children in(R column, Object... values) {
         return in(true, column, values);
@@ -95,7 +119,7 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 字段 IN (v0, v1, ...)
-     * <p>例: in("id", 1, 2, 3, 4, 5)</p>
+     * <p>例: in(true, "id", 1, 2, 3, 4, 5)</p>
      *
      * <li> 注意!当数组为 空或null 时, sql会拼接为:WHERE (字段名 IN ()), 执行时报错</li>
      * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
@@ -108,7 +132,15 @@ public interface Func<Children, R> extends Serializable {
     Children in(boolean condition, R column, Object... values);
 
     /**
-     * ignore
+     * 字段 NOT IN (value.get(0), value.get(1), ...)
+     * <p>例: notIn("id", Arrays.asList(1, 2, 3, 4, 5))</p>
+     *
+     * <li> 注意!当集合为 空或null 时, sql会拼接为:WHERE (字段名 NOT IN ()), 执行时报错</li>
+     * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
+     *
+     * @param column    字段
+     * @param coll      数据集合
+     * @return children
      */
     default Children notIn(R column, Collection<?> coll) {
         return notIn(true, column, coll);
@@ -116,7 +148,7 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 字段 NOT IN (value.get(0), value.get(1), ...)
-     * <p>例: notIn("id", Arrays.asList(1, 2, 3, 4, 5))</p>
+     * <p>例: notIn(true, "id", Arrays.asList(1, 2, 3, 4, 5))</p>
      *
      * <li> 注意!当集合为 空或null 时, sql会拼接为:WHERE (字段名 NOT IN ()), 执行时报错</li>
      * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
@@ -129,15 +161,23 @@ public interface Func<Children, R> extends Serializable {
     Children notIn(boolean condition, R column, Collection<?> coll);
 
     /**
-     * ignore
+     * 字段 NOT IN (v0, v1, ...)
+     * <p>例: notIn("id", 1, 2, 3, 4, 5)</p>
+     *
+     * <li> 注意!当数组为 空或null 时, sql会拼接为:WHERE (字段名 NOT IN ()), 执行时报错</li>
+     * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
+     *
+     * @param column    字段
+     * @param values    数据数组
+     * @return children
      */
-    default Children notIn(R column, Object... value) {
-        return notIn(true, column, value);
+    default Children notIn(R column, Object... values) {
+        return notIn(true, column, values);
     }
 
     /**
      * 字段 NOT IN (v0, v1, ...)
-     * <p>例: notIn("id", 1, 2, 3, 4, 5)</p>
+     * <p>例: notIn(true, "id", 1, 2, 3, 4, 5)</p>
      *
      * <li> 注意!当数组为 空或null 时, sql会拼接为:WHERE (字段名 NOT IN ()), 执行时报错</li>
      * <li> 若要在特定条件下不拼接, 可在 condition 条件中判断 </li>
@@ -150,103 +190,141 @@ public interface Func<Children, R> extends Serializable {
     Children notIn(boolean condition, R column, Object... values);
 
     /**
-     * ignore
+     * 字段 IN ( sql语句 )
+     * <p>!! sql 注入方式的 in 方法 !!</p>
+     * <p>例1: inSql("id", "1")</p>
+     * <p>例2: inSql("id", "select id from table where id &lt; 3")</p>
+     *
+     * @param column    字段
+     * @param sql   sql语句
+     * @return children
      */
-    default Children inSql(R column, String inValue) {
-        return inSql(true, column, inValue);
+    default Children inSql(R column, String sql) {
+        return inSql(true, column, sql);
     }
 
     /**
      * 字段 IN ( sql语句 )
      * <p>!! sql 注入方式的 in 方法 !!</p>
-     * <p>例1: inSql("id", "1, 2, 3, 4, 5, 6")</p>
-     * <p>例2: inSql("id", "select id from table where id &lt; 3")</p>
+     * <p>例1: inSql(true, "id", "1")</p>
+     * <p>例2: inSql(true, "id", "select id from table where id &lt; 3")</p>
      *
      * @param condition 执行条件
      * @param column    字段
-     * @param inValue   sql语句
+     * @param sql   sql语句
      * @return children
      */
-    Children inSql(boolean condition, R column, String inValue);
+    Children inSql(boolean condition, R column, String sql);
 
     /**
      * 字段 &gt; ( sql语句 )
-     * <p>例1: gtSql("id", "1, 2, 3, 4, 5, 6")</p>
-     * <p>例1: gtSql("id", "select id from table where name = 'JunJun'")</p>
+     * <p>例1: gtSql(true, "id", "1")</p>
+     * <p>例1: gtSql(true, "id", "select id from table where name = 'JunJun'")</p>
      *
-     * @param condition
-     * @param column
-     * @param inValue
-     * @return
+     * @param condition 执行条件
+     * @param column    字段
+     * @param sql       sql语句
+     * @return children
      */
-    Children gtSql(boolean condition, R column, String inValue);
+    Children gtSql(boolean condition, R column, String sql);
 
     /**
-     * ignore
+     * 字段 &gt; ( sql语句 )
+     * <p>例1: gtSql("id", "1")</p>
+     * <p>例1: gtSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param column 字段
+     * @param sql    sql语句
+     * @return children
      */
-    default Children gtSql(R column, String inValue) {
-        return gtSql(true, column, inValue);
+    default Children gtSql(R column, String sql) {
+        return gtSql(true, column, sql);
     }
 
     /**
      * 字段 >= ( sql语句 )
-     * <p>例1: geSql("id", "1, 2, 3, 4, 5, 6")</p>
-     * <p>例1: geSql("id", "select id from table where name = 'JunJun'")</p>
+     * <p>例1: geSql(true, "id", "1")</p>
+     * <p>例1: geSql(true, "id", "select id from table where name = 'JunJun'")</p>
      *
-     * @param condition
-     * @param column
-     * @param inValue
-     * @return
+     * @param condition 执行条件
+     * @param column    字段
+     * @param sql       sql语句
+     * @return children
      */
-    Children geSql(boolean condition, R column, String inValue);
+    Children geSql(boolean condition, R column, String sql);
 
     /**
-     * ignore
+     * 字段 >= ( sql语句 )
+     * <p>例1: geSql("id", "1")</p>
+     * <p>例1: geSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param column 字段
+     * @param sql    sql语句
+     * @return children
      */
-    default Children geSql(R column, String inValue) {
-        return geSql(true, column, inValue);
+    default Children geSql(R column, String sql) {
+        return geSql(true, column, sql);
     }
 
     /**
      * 字段 &lt; ( sql语句 )
-     * <p>例1: ltSql("id", "1, 2, 3, 4, 5, 6")</p>
-     * <p>例1: ltSql("id", "select id from table where name = 'JunJun'")</p>
+     * <p>例1: ltSql(true, "id", "1")</p>
+     * <p>例1: ltSql(true , "id", "select id from table where name = 'JunJun'")</p>
      *
-     * @param condition
-     * @param column
-     * @param inValue
-     * @return
+     * @param condition 执行条件
+     * @param column 字段
+     * @param sql sql语句
+     * @return children
      */
-    Children ltSql(boolean condition, R column, String inValue);
+    Children ltSql(boolean condition, R column, String sql);
 
     /**
-     * ignore
+     * 字段 &lt; ( sql语句 )
+     * <p>例1: ltSql("id", "1")</p>
+     * <p>例1: ltSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param column 字段
+     * @param sql    sql语句
+     * @return children
      */
-    default Children ltSql(R column, String inValue) {
-        return ltSql(true, column, inValue);
+    default Children ltSql(R column, String sql) {
+        return ltSql(true, column, sql);
     }
 
     /**
      * 字段 <= ( sql语句 )
-     * <p>例1: leSql("id", "1, 2, 3, 4, 5, 6")</p>
-     * <p>例1: leSql("id", "select id from table where name = 'JunJun'")</p>
+     * <p>例1: leSql(true, "id", "1")</p>
+     * <p>例1: leSql(true ,"id", "select id from table where name = 'JunJun'")</p>
      *
-     * @param condition
-     * @param column
-     * @param inValue
-     * @return
+     * @param condition 执行条件
+     * @param column    字段
+     * @param sql       sql语句
+     * @return children
      */
-    Children leSql(boolean condition, R column, String inValue);
+    Children leSql(boolean condition, R column, String sql);
 
     /**
-     * ignore
+     * 字段 <= ( sql语句 )
+     * <p>例1: leSql("id", "1")</p>
+     * <p>例1: leSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param column 字段
+     * @param inValue  sql语句
+     * @return children
      */
     default Children leSql(R column, String inValue) {
         return leSql(true, column, inValue);
     }
 
     /**
-     * ignore
+     * 字段 NOT IN ( sql语句 )
+     * <p>!! sql 注入方式的 not in 方法 !!</p>
+     * <p>例1: notInSql("id", "1, 2, 3, 4, 5, 6")</p>
+     * <p>例2: notInSql("id", "select id from table where id &lt; 3")</p>
+     *
+     * @param column  字段
+     * @param inValue sql语句 ---&gt; 1,2,3,4,5,6 或者 select id from table where id &lt; 3
+     * @return children
      */
     default Children notInSql(R column, String inValue) {
         return notInSql(true, column, inValue);
@@ -255,8 +333,8 @@ public interface Func<Children, R> extends Serializable {
     /**
      * 字段 NOT IN ( sql语句 )
      * <p>!! sql 注入方式的 not in 方法 !!</p>
-     * <p>例1: notInSql("id", "1, 2, 3, 4, 5, 6")</p>
-     * <p>例2: notInSql("id", "select id from table where id &lt; 3")</p>
+     * <p>例1: notInSql(true, "id", "1, 2, 3, 4, 5, 6")</p>
+     * <p>例2: notInSql(true, "id", "select id from table where id &lt; 3")</p>
      *
      * @param condition 执行条件
      * @param column    字段
@@ -267,7 +345,7 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 分组:GROUP BY 字段, ...
-     * <p>例: groupBy("id")</p>
+     * <p>例: groupBy(true, "id")</p>
      *
      * @param condition 执行条件
      * @param column    单个字段
@@ -275,13 +353,20 @@ public interface Func<Children, R> extends Serializable {
      */
     Children groupBy(boolean condition, R column);
 
+    /**
+     * 分组:GROUP BY 字段, ...
+     * <p>例: groupBy("id")</p>
+     *
+     * @param column 单个字段
+     * @return children
+     */
     default Children groupBy(R column) {
         return groupBy(true, column);
     }
 
     /**
      * 分组:GROUP BY 字段, ...
-     * <p>例: groupBy(Arrays.asList("id", "name"))</p>
+     * <p>例: groupBy(true, Arrays.asList("id", "name"))</p>
      *
      * @param condition 执行条件
      * @param columns   字段数组
@@ -289,26 +374,52 @@ public interface Func<Children, R> extends Serializable {
      */
     Children groupBy(boolean condition, List<R> columns);
 
+    /**
+     * 分组:GROUP BY 字段, ...
+     * <p>例: groupBy(Arrays.asList("id", "name"))</p>
+     *
+     * @param columns 字段数组
+     * @return children
+     */
     default Children groupBy(List<R> columns) {
         return groupBy(true, columns);
     }
 
+    /**
+     * 分组:GROUP BY 字段, ...
+     * <p>例: groupBy("id", "name")</p>
+     *
+     * @param column  单个字段
+     * @param columns 字段数组
+     * @return children
+     */
     default Children groupBy(R column, R... columns) {
         return groupBy(true, column, columns);
     }
 
     /**
      * 分组:GROUP BY 字段, ...
+     * <p>例: groupBy(true, "id", "name")</p>
+     *
+     * @param condition 执行条件
+     * @param column    单个字段
+     * @param columns   字段数组
+     * @return children
      */
     Children groupBy(boolean condition, R column, R... columns);
 
     /**
      * 分组:GROUP BY 字段, ...
+     * <p>例: groupBy(true, "id", Arrays.asList("name"))</p>
+     *
+     * @param condition 执行条件
+     * @param column    单个字段
+     * @param columns   字段数组
+     * @return children
      * @since 3.5.4
      */
     Children groupBy(boolean condition, R column, List<R> columns);
 
-
     /**
      * 排序:ORDER BY 字段, ... ASC
      * <p>例: orderByAsc(true, "id")</p>
@@ -321,6 +432,13 @@ public interface Func<Children, R> extends Serializable {
         return orderBy(condition, true, column);
     }
 
+    /**
+     * 排序:ORDER BY 字段, ... ASC
+     * <p>例: orderByAsc("id")</p>
+     *
+     * @param column 单个字段
+     * @return children
+     */
     default Children orderByAsc(R column) {
         return orderByAsc(true, column);
     }
@@ -337,16 +455,34 @@ public interface Func<Children, R> extends Serializable {
         return orderBy(condition, true, columns);
     }
 
+    /**
+     * 排序:ORDER BY 字段, ... ASC
+     * <p>例: orderByAsc(Arrays.asList("id", "name"))</p>
+     *
+     * @param columns 字段数组
+     * @return children
+     */
     default Children orderByAsc(List<R> columns) {
         return orderByAsc(true, columns);
     }
 
+    /**
+     * 排序:ORDER BY 字段, ... ASC
+     *
+     * @param column  字段
+     * @param columns 字段数组
+     * @return children
+     */
     default Children orderByAsc(R column, R... columns) {
         return orderByAsc(true, column, columns);
     }
 
     /**
      * 排序:ORDER BY 字段, ... ASC
+     *
+     * @param condition 执行条件
+     * @param column    字段
+     * @param columns   字段数组
      */
     default Children orderByAsc(boolean condition, R column, R... columns) {
         return orderBy(condition, true, column, columns);
@@ -354,7 +490,11 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 排序:ORDER BY 字段, ... ASC
+     * <p>例: orderByAsc(true, Arrays.asList("id", "name"))</p>
      *
+     * @param condition 执行条件
+     * @param columns   字段数组
+     * @return children
      * @since 3.5.4
      */
     default Children orderByAsc(boolean condition, R column, List<R> columns) {
@@ -373,6 +513,13 @@ public interface Func<Children, R> extends Serializable {
         return orderBy(condition, false, column);
     }
 
+    /**
+     * 排序:ORDER BY 字段, ... DESC
+     * <p>例: orderByDesc("id")</p>
+     *
+     * @param column    字段
+     * @return children
+     */
     default Children orderByDesc(R column) {
         return orderByDesc(true, column);
     }
@@ -389,16 +536,31 @@ public interface Func<Children, R> extends Serializable {
         return orderBy(condition, false, columns);
     }
 
+    /**
+     * 排序:ORDER BY 字段, ... DESC
+     *
+     * @param columns 字段列表
+     */
     default Children orderByDesc(List<R> columns) {
         return orderByDesc(true, columns);
     }
 
+    /**
+     * 排序:ORDER BY 字段, ... DESC
+     *
+     * @param column  单个字段
+     * @param columns 字段列表
+     */
     default Children orderByDesc(R column, R... columns) {
         return orderByDesc(true, column, columns);
     }
 
     /**
      * 排序:ORDER BY 字段, ... DESC
+     *
+     * @param condition 执行条件
+     * @param column    单个字段
+     * @param columns   字段列表
      */
     default Children orderByDesc(boolean condition, R column, R... columns) {
         return orderBy(condition, false, column, CollectionUtils.toList(columns));
@@ -407,6 +569,9 @@ public interface Func<Children, R> extends Serializable {
     /**
      * 排序:ORDER BY 字段, ... DESC
      *
+     * @param condition 执行条件
+     * @param column    单个字段
+     * @param columns   字段列表
      * @since 3.5.4
      */
     default Children orderByDesc(boolean condition, R column, List<R> columns) {
@@ -438,20 +603,34 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * 排序:ORDER BY 字段, ...
+     *
+     * @param condition 执行条件
+     * @param isAsc     是否是 ASC 排序
+     * @param columns   字段列表
+     * @return children
      */
     Children orderBy(boolean condition, boolean isAsc, R column, R... columns);
 
-
     /**
      * 排序:ORDER BY 字段, ...
      *
+     * @param condition 执行条件
+     * @param isAsc     是否是 ASC 排序
+     * @param columns   字段列表
+     * @return children
      * @since 3.5.4
      */
     Children orderBy(boolean condition, boolean isAsc, R column, List<R> columns);
 
 
     /**
-     * ignore
+     * HAVING ( sql语句 )
+     * <p>例1: having("sum(age) &gt; 10")</p>
+     * <p>例2: having("sum(age) &gt; {0}", 10)</p>
+     *
+     * @param sqlHaving sql 语句
+     * @param params    参数数组
+     * @return children
      */
     default Children having(String sqlHaving, Object... params) {
         return having(true, sqlHaving, params);
@@ -459,8 +638,8 @@ public interface Func<Children, R> extends Serializable {
 
     /**
      * HAVING ( sql语句 )
-     * <p>例1: having("sum(age) &gt; 10")</p>
-     * <p>例2: having("sum(age) &gt; {0}", 10)</p>
+     * <p>例1: having(true, "sum(age) &gt; 10")</p>
+     * <p>例2: having(true, "sum(age) &gt; {0}", 10)</p>
      *
      * @param condition 执行条件
      * @param sqlHaving sql 语句
@@ -470,7 +649,10 @@ public interface Func<Children, R> extends Serializable {
     Children having(boolean condition, String sqlHaving, Object... params);
 
     /**
-     * ignore
+     * 消费函数
+     *
+     * @param consumer 消费函数
+     * @return children
      */
     default Children func(Consumer<Children> consumer) {
         return func(true, consumer);
@@ -479,7 +661,8 @@ public interface Func<Children, R> extends Serializable {
     /**
      * 消费函数
      *
-     * @param consumer 消费函数
+     * @param condition 执行条件
+     * @param consumer  消费函数
      * @return children
      * @since 3.3.1
      */

+ 40 - 7
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Join.java

@@ -27,7 +27,9 @@ import java.io.Serializable;
 public interface Join<Children> extends Serializable {
 
     /**
-     * ignore
+     * 拼接 OR
+     *
+     * @return children
      */
     default Children or() {
         return or(true);
@@ -42,7 +44,15 @@ public interface Join<Children> extends Serializable {
     Children or(boolean condition);
 
     /**
-     * ignore
+     * 拼接 sql
+     * <p>!! 会有 sql 注入风险 !!</p>
+     * <p>例1: apply("id = 1")</p>
+     * <p>例2: apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")</p>
+     * <p>例3: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", LocalDate.now())</p>
+     * <p>例4: apply("name={0,javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler}", "老王")</p>
+     *
+     * @param values    数据数组
+     * @return children
      */
     default Children apply(String applySql, Object... values) {
         return apply(true, applySql, values);
@@ -63,7 +73,12 @@ public interface Join<Children> extends Serializable {
     Children apply(boolean condition, String applySql, Object... values);
 
     /**
-     * ignore
+     * 无视优化规则直接拼接到 sql 的最后(有sql注入的风险,请谨慎使用)
+     * <p>例: last("limit 1")</p>
+     * <p>注意只能调用一次,多次调用以最后一次为准</p>
+     *
+     * @param lastSql   sql语句
+     * @return children
      */
     default Children last(String lastSql) {
         return last(true, lastSql);
@@ -81,7 +96,10 @@ public interface Join<Children> extends Serializable {
     Children last(boolean condition, String lastSql);
 
     /**
-     * ignore
+     * sql 注释(会拼接在 sql 的最后面)
+     *
+     * @param comment   sql注释
+     * @return children
      */
     default Children comment(String comment) {
         return comment(true, comment);
@@ -97,7 +115,10 @@ public interface Join<Children> extends Serializable {
     Children comment(boolean condition, String comment);
 
     /**
-     * ignore
+     * sql 起始句(会拼接在SQL语句的起始处)
+     *
+     * @param firstSql  起始语句
+     * @return children
      */
     default Children first(String firstSql) {
         return first(true, firstSql);
@@ -114,7 +135,13 @@ public interface Join<Children> extends Serializable {
     Children first(boolean condition, String firstSql);
 
     /**
-     * ignore
+     * 拼接 EXISTS ( sql语句 )
+     * <p>!! sql 注入方法 !!</p>
+     * <p>例: exists("select id from table where age = 1")</p>
+     *
+     * @param existsSql sql语句
+     * @param values    数据数组
+     * @return children
      */
     default Children exists(String existsSql, Object... values) {
         return exists(true, existsSql, values);
@@ -133,7 +160,13 @@ public interface Join<Children> extends Serializable {
     Children exists(boolean condition, String existsSql, Object... values);
 
     /**
-     * ignore
+     * 拼接 NOT EXISTS ( sql语句 )
+     * <p>!! sql 注入方法 !!</p>
+     * <p>例: notExists("select id from table where age = 1")</p>
+     *
+     * @param existsSql sql语句
+     * @param values    数据数组
+     * @return children
      */
     default Children notExists(String existsSql, Object... values) {
         return notExists(true, existsSql, values);

+ 28 - 4
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Nested.java

@@ -29,7 +29,13 @@ import java.util.function.Consumer;
 public interface Nested<Param, Children> extends Serializable {
 
     /**
-     * ignore
+     * AND 嵌套
+     * <p>
+     * 例: and(i -&gt; i.eq("name", "李白").ne("status", "活着"))
+     * </p>
+     *
+     * @param consumer  消费函数
+     * @return children
      */
     default Children and(Consumer<Param> consumer) {
         return and(true, consumer);
@@ -48,7 +54,13 @@ public interface Nested<Param, Children> extends Serializable {
     Children and(boolean condition, Consumer<Param> consumer);
 
     /**
-     * ignore
+     * OR 嵌套
+     * <p>
+     * 例: or(i -&gt; i.eq("name", "李白").ne("status", "活着"))
+     * </p>
+     *
+     * @param consumer  消费函数
+     * @return children
      */
     default Children or(Consumer<Param> consumer) {
         return or(true, consumer);
@@ -67,7 +79,13 @@ public interface Nested<Param, Children> extends Serializable {
     Children or(boolean condition, Consumer<Param> consumer);
 
     /**
-     * ignore
+     * 正常嵌套 不带 AND 或者 OR
+     * <p>
+     * 例: nested(i -&gt; i.eq("name", "李白").ne("status", "活着"))
+     * </p>
+     *
+     * @param consumer  消费函数
+     * @return children
      */
     default Children nested(Consumer<Param> consumer) {
         return nested(true, consumer);
@@ -86,7 +104,13 @@ public interface Nested<Param, Children> extends Serializable {
     Children nested(boolean condition, Consumer<Param> consumer);
 
     /**
-     * ignore
+     * not嵌套
+     * <p>
+     * 例: not(i -&gt; i.eq("name", "李白").ne("status", "活着"))
+     * </p>
+     *
+     * @param consumer  消费函数
+     * @return children
      */
     default Children not(Consumer<Param> consumer) {
         return not(true, consumer);

+ 19 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/query/Query.java

@@ -29,7 +29,10 @@ import java.util.function.Predicate;
 public interface Query<Children, T, R> extends Serializable {
 
     /**
-     * ignore
+     * 指定查询字段
+     *
+     * @param columns 字段列表
+     * @return children
      */
     @SuppressWarnings("unchecked")
     default Children select(R... columns) {
@@ -37,7 +40,11 @@ public interface Query<Children, T, R> extends Serializable {
     }
 
     /**
-     * ignore
+     * 指定查询字段
+     *
+     * @param condition 执行条件
+     * @param columns   字段列表
+     * @return children
      */
     @SuppressWarnings("unchecked")
     default Children select(boolean condition, R... columns) {
@@ -45,19 +52,26 @@ public interface Query<Children, T, R> extends Serializable {
     }
 
     /**
-     * ignore
+     * 指定查询字段
+     *
+     * @param columns   字段列表
+     * @return children
      */
     default Children select(List<R> columns) {
         return select(true, columns);
     }
 
     /**
-     * ignore
+     * 指定查询字段
+     *
+     * @param condition 执行条件
+     * @param columns   字段列表
+     * @return children
      */
     Children select(boolean condition, List<R> columns);
 
     /**
-     * ignore
+     * 过滤查询的字段信息(主键除外!)
      * <p>注意只有内部有 entity 才能使用该方法</p>
      */
     default Children select(Predicate<TableFieldInfo> predicate) {

+ 25 - 8
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/update/Update.java

@@ -24,7 +24,11 @@ import java.io.Serializable;
 public interface Update<Children, R> extends Serializable {
 
     /**
-     * ignore
+     * 设置 更新 SQL 的 SET 片段
+     *
+     * @param column 字段
+     * @param val    值
+     * @return children
      */
     default Children set(R column, Object val) {
         return set(true, column, val);
@@ -43,7 +47,12 @@ public interface Update<Children, R> extends Serializable {
     }
 
     /**
-     * ignore
+     * 设置 更新 SQL 的 SET 片段
+     *
+     * @param column  字段
+     * @param val     值
+     * @param mapping 例: javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler
+     * @return children
      */
     default Children set(R column, Object val, String mapping) {
         return set(true, column, val, mapping);
@@ -61,7 +70,14 @@ public interface Update<Children, R> extends Serializable {
     Children set(boolean condition, R column, Object val, String mapping);
 
     /**
-     * ignore
+     * 设置 更新 SQL 的 SET 片段
+     *
+     * @param setSql set sql
+     *               例1: setSql("id=1")
+     *               例2: apply("dateColumn={0}", LocalDate.now())
+     *               例3: apply("dateColumn={0}", LocalDate.now())
+     *               例4: apply("name={0,javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler}", "老王")
+     * @return children
      */
     default Children setSql(String setSql, Object... params) {
         return setSql(true, setSql, params);
@@ -70,11 +86,12 @@ public interface Update<Children, R> extends Serializable {
     /**
      * 设置 更新 SQL 的 SET 片段
      *
-     * @param setSql set sql
-     *               例1: setSql("id=1")
-     *               例2: apply("dateColumn={0}", LocalDate.now())
-     *               例3: apply("dateColumn={0}", LocalDate.now())
-     *               例4: apply("name={0,javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler}", "老王")
+     * @param condition 执行条件
+     * @param setSql    set sql
+     *                  例1: setSql("id=1")
+     *                  例2: apply("dateColumn={0}", LocalDate.now())
+     *                  例3: apply("dateColumn={0}", LocalDate.now())
+     *                  例4: apply("name={0,javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler}", "老王")
      * @return children
      */
     Children setSql(boolean condition, String setSql, Object... params);

+ 1 - 1
mybatis-plus-extension/build.gradle

@@ -24,6 +24,6 @@ dependencies {
     implementation "com.github.ben-manes.caffeine:caffeine:2.9.3"
     testImplementation "com.github.pagehelper:pagehelper:5.3.1"
     testImplementation "com.google.guava:guava:31.1-jre"
-    testImplementation "io.github.classgraph:classgraph:+"
+    testImplementation "io.github.classgraph:classgraph:4.8.163"
     testImplementation "${lib.h2}"
 }

+ 17 - 4
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java

@@ -33,6 +33,8 @@ import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.mybatis.spring.SqlSessionTemplate;
 import org.mybatis.spring.SqlSessionUtils;
+import org.springframework.aop.framework.AopProxyUtils;
+import org.springframework.aop.support.AopUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.core.convert.support.DefaultConversionService;
@@ -82,14 +84,25 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
 
     private volatile SqlSessionFactory sqlSessionFactory;
 
-    @SuppressWarnings("rawtypes")
+    @SuppressWarnings({"rawtypes", "deprecation"})
     protected SqlSessionFactory getSqlSessionFactory() {
         if (this.sqlSessionFactory == null) {
             synchronized (this) {
                 if (this.sqlSessionFactory == null) {
-                    MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(this.baseMapper);
-                    SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
-                    this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
+                    Object target = this.baseMapper;
+                    // 这个检查目前看着来说基本上可以不用判断Aop是不是存在了.
+                    if (com.baomidou.mybatisplus.extension.toolkit.AopUtils.isLoadSpringAop()) {
+                        if (AopUtils.isAopProxy(this.baseMapper)) {
+                            target = AopProxyUtils.getSingletonTarget(this.baseMapper);
+                        }
+                    }
+                    if (target != null) {
+                        MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(target);
+                        SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
+                        this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
+                    } else {
+                        this.sqlSessionFactory = GlobalConfigUtils.currentSessionFactory(this.entityClass);
+                    }
                 }
             }
         }

+ 27 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/AopUtils.java

@@ -30,8 +30,35 @@ import java.lang.reflect.Field;
  */
 public class AopUtils {
 
+    /**
+     * 是否加载Spring-Aop模块
+     *
+     * @since 3.5.4
+     */
+    private static boolean loadAop = false;
+
+    static {
+        try {
+            ClassUtils.toClassConfident("org.springframework.aop.framework.AopProxyUtils");
+            loadAop = true;
+        } catch (Exception exception) {
+            // ignore
+        }
+    }
+
     private static final Log logger = LogFactory.getLog(AopUtils.class);
 
+    /**
+     * 是否加载Spring-Aop模块
+     *
+     * @return 是否加载Spring-Aop模块
+     * @since 3.5.5
+     */
+    public static boolean isLoadSpringAop() {
+        return loadAop;
+    }
+
+
     /**
      * 获取源目标对象
      *

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

@@ -33,7 +33,7 @@ public class DB2TypeConvert implements ITypeConvert {
     public static final DB2TypeConvert INSTANCE = new DB2TypeConvert();
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
      */
     @Override
     public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {

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

@@ -50,7 +50,6 @@ public class DmTypeConvert implements ITypeConvert {
      * @param config    全局配置
      * @param fieldType 字段类型
      * @return 对应的数据类型
-     * @inheritDoc
      */
     @Override
     public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {

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

@@ -34,7 +34,7 @@ public class FirebirdTypeConvert implements ITypeConvert {
     public static final FirebirdTypeConvert INSTANCE = new FirebirdTypeConvert();
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
      */
     @Override
     public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {

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

@@ -34,7 +34,7 @@ public class MySqlTypeConvert implements ITypeConvert {
     public static final MySqlTypeConvert INSTANCE = new MySqlTypeConvert();
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
      */
     @Override
     public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {

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

@@ -34,7 +34,7 @@ public class PostgreSqlTypeConvert implements ITypeConvert {
     public static final PostgreSqlTypeConvert INSTANCE = new PostgreSqlTypeConvert();
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
      */
     @Override
     public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {

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

@@ -34,7 +34,7 @@ public class SqlServerTypeConvert implements ITypeConvert {
     public static final SqlServerTypeConvert INSTANCE = new SqlServerTypeConvert();
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
      */
     @Override
     public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {

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

@@ -35,7 +35,8 @@ public class SqliteTypeConvert implements ITypeConvert {
     public static final SqliteTypeConvert INSTANCE = new SqliteTypeConvert();
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
+     *
      * @see MySqlTypeConvert#toDateType(GlobalConfig, String)
      */
     @Override

+ 2 - 1
mybatis-plus/build.gradle

@@ -12,7 +12,8 @@ dependencies {
     testImplementation "${lib.'javax.servlet-api'}"
 
     testImplementation "${lib.'spring-test'}"
-
+    testImplementation "${lib.'spring-aop'}"
+    testImplementation "${lib.'aspectjweaver'}"
     testImplementation "${lib."jackson"}"
     testImplementation "${lib."fastjson"}"
     testImplementation "${lib."gson"}"

+ 34 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AopConfig1.java

@@ -0,0 +1,34 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * @author nieqiurong
+ */
+@Aspect
+@EnableAspectJAutoProxy
+public class AopConfig1 {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AopConfig1.class);
+
+    @Pointcut("execution(* com.baomidou.mybatisplus.test.h2.issues.aop.mapper..*.*(..))")
+    public void point() {
+    }
+
+    @Before("point()")
+    public void before() {
+        LOGGER.info("before ...");
+    }
+
+    @After("point()")
+    public void after() {
+        LOGGER.info("After ...");
+    }
+
+}

+ 26 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AopConfig2.java

@@ -0,0 +1,26 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author nieqiurong
+ */
+@Aspect
+public class AopConfig2 {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AopConfig2.class);
+
+    @Pointcut("execution(* com.baomidou.mybatisplus.test.h2.issues.aop.mapper..*.*(..))")
+    public void point() {
+    }
+
+    @Before("point()")
+    public void before() {
+        LOGGER.info("before ...");
+    }
+
+}

+ 41 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/AppConfig.java

@@ -0,0 +1,41 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.h2.Driver;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+
+import javax.sql.DataSource;
+
+/**
+ * @author nieqiurong
+ */
+@Configuration
+@ComponentScan("com.baomidou.mybatisplus.test.h2.issues.aop")
+@MapperScan("com.baomidou.mybatisplus.test.h2.issues.aop.mapper")
+public class AppConfig {
+
+    @Bean
+    public DataSource dataSource() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriver(new Driver());
+        dataSource.setUrl("jdbc:h2:mem:testa;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        return dataSource;
+    }
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
+        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
+        mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
+        return mybatisSqlSessionFactoryBean.getObject();
+    }
+
+}

+ 44 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/MultiAopTest.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class, AopConfig2.class})
+public class MultiAopTest {
+
+    @Autowired
+    private IDemoService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+}

+ 45 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/NoAopTest.java

@@ -0,0 +1,45 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class})
+public class NoAopTest {
+
+    @Autowired
+    private IDemoService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+
+}

+ 44 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/SingleAopTest.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop;
+
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class, AopConfig1.class})
+public class SingleAopTest {
+
+    @Autowired
+    private IDemoService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/entity/Demo.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.entity;
+
+import lombok.Data;
+
+/**
+ * @author nieqiurong
+ */
+@Data
+public class Demo {
+
+    private Long id;
+
+    private String name;
+
+}

+ 13 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/mapper/DemoMapper.java

@@ -0,0 +1,13 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author nieqiurong
+ */
+@Mapper
+public interface DemoMapper extends BaseMapper<Demo> {
+
+}

+ 11 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/service/IDemoService.java

@@ -0,0 +1,11 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+
+/**
+ * @author nieqiurong
+ */
+public interface IDemoService extends IService<Demo> {
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/aop/service/impl/DemoServiceImpl.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.issues.aop.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.baomidou.mybatisplus.test.h2.issues.aop.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.aop.mapper.DemoMapper;
+import com.baomidou.mybatisplus.test.h2.issues.aop.service.IDemoService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author nieqiurong
+ */
+@Service
+public class DemoServiceImpl extends ServiceImpl<DemoMapper, Demo> implements IDemoService {
+
+}

+ 40 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/AppConfig.java

@@ -0,0 +1,40 @@
+
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.h2.Driver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+
+import javax.sql.DataSource;
+
+/**
+ * @author nieqiurong
+ */
+@Configuration
+@ComponentScan("com.baomidou.mybatisplus.test.h2.issues.repositoryscan")
+public class AppConfig {
+
+    @Bean
+    public DataSource dataSource() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriver(new Driver());
+        dataSource.setUrl("jdbc:h2:mem:testa;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        return dataSource;
+    }
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
+        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
+        mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
+        return mybatisSqlSessionFactoryBean.getObject();
+    }
+
+}

+ 43 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/AppConfigWithMapperScan.java

@@ -0,0 +1,43 @@
+
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.h2.Driver;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+import org.springframework.stereotype.Repository;
+
+import javax.sql.DataSource;
+
+/**
+ * @author nieqiurong
+ */
+@Configuration
+@ComponentScan("com.baomidou.mybatisplus.test.h2.issues.repositoryscan")
+@MapperScan(value = "com.baomidou.mybatisplus.test.h2.issues.repositoryscan.mapper", annotationClass = Repository.class)
+public class AppConfigWithMapperScan {
+
+    @Bean
+    public DataSource dataSource() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriver(new Driver());
+        dataSource.setUrl("jdbc:h2:mem:testa;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        return dataSource;
+    }
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
+        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
+        mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
+        return mybatisSqlSessionFactoryBean.getObject();
+    }
+
+}

+ 44 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/RepositoryDefaultScanTest.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan;
+
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.service.IDemoRepositoryService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class})
+public class RepositoryDefaultScanTest {
+
+    @Autowired
+    private IDemoRepositoryService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+}

+ 44 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/RepositoryMapperScanTest.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan;
+
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.service.IDemoRepositoryService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfigWithMapperScan.class})
+public class RepositoryMapperScanTest {
+
+    @Autowired
+    private IDemoRepositoryService demoService;
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Test
+    void test() throws SQLException {
+        new SqlRunner(dataSource.getConnection()).run(
+            """
+                 CREATE TABLE IF NOT EXISTS demo (
+                      id BIGINT NOT NULL AUTO_INCREMENT,
+                      name VARCHAR(30) NULL DEFAULT NULL ,
+                      PRIMARY KEY (id)
+                 );
+                """
+        );
+        demoService.save(new Demo());
+        demoService.saveBatch(List.of(new Demo()));
+    }
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/entity/Demo.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan.entity;
+
+import lombok.Data;
+
+/**
+ * @author nieqiurong
+ */
+@Data
+public class Demo {
+
+    private Long id;
+
+    private String name;
+
+}

+ 13 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/mapper/DemoRepositoryMapper.java

@@ -0,0 +1,13 @@
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.entity.Demo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author nieqiurong
+ */
+@Repository
+public interface DemoRepositoryMapper extends BaseMapper<Demo> {
+
+}

+ 11 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/service/IDemoRepositoryService.java

@@ -0,0 +1,11 @@
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.entity.Demo;
+
+/**
+ * @author nieqiurong
+ */
+public interface IDemoRepositoryService extends IService<Demo> {
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/issues/repositoryscan/service/impl/DemoRepositoryServiceImpl.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.issues.repositoryscan.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.entity.Demo;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.mapper.DemoRepositoryMapper;
+import com.baomidou.mybatisplus.test.h2.issues.repositoryscan.service.IDemoRepositoryService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author nieqiurong
+ */
+@Service
+public class DemoRepositoryServiceImpl extends ServiceImpl<DemoRepositoryMapper, Demo> implements IDemoRepositoryService {
+
+}

+ 88 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/AppConfig.java

@@ -0,0 +1,88 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.h2.Driver;
+import org.mybatis.spring.annotation.MapperScan;
+import org.mybatis.spring.annotation.MapperScans;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import javax.sql.DataSource;
+
+/**
+ * @author nieqiurong
+ */
+@ComponentScan("com.baomidou.mybatisplus.test.multisqlsessionfactory")
+@MapperScans(
+    {
+        @MapperScan(value = "com.baomidou.mybatisplus.test.multisqlsessionfactory.a.mapper", sqlSessionFactoryRef = "sqlSessionFactory1"),
+        @MapperScan(value = "com.baomidou.mybatisplus.test.multisqlsessionfactory.b.mapper", sqlSessionFactoryRef = "sqlSessionFactory2")
+    }
+)
+@Configuration
+public class AppConfig {
+
+    @Bean
+    public DataSource dataSourceA() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriver(new Driver());
+        dataSource.setUrl("jdbc:h2:mem:testa;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        return dataSource;
+    }
+
+    @Bean
+    public DataSourceTransactionManager transactionManagerA(DataSource dataSourceA) {
+        return new DataSourceTransactionManager(dataSourceA);
+    }
+
+    @Bean
+    public TransactionTemplate transactionTemplateA(DataSourceTransactionManager transactionManagerA) {
+        return new TransactionTemplate(transactionManagerA);
+    }
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory1(DataSource dataSourceA) throws Exception {
+        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
+        mybatisSqlSessionFactoryBean.setDataSource(dataSourceA);
+        mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
+        return mybatisSqlSessionFactoryBean.getObject();
+    }
+
+    @Bean
+    public DataSource dataSourceB() {
+        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
+        dataSource.setDriver(new Driver());
+        dataSource.setUrl("jdbc:h2:mem:testb;MODE=mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+        dataSource.setUsername("sa");
+        dataSource.setPassword("");
+        return dataSource;
+    }
+
+    @Bean
+    public DataSourceTransactionManager transactionManagerB(DataSource dataSourceB) {
+        return new DataSourceTransactionManager(dataSourceB);
+    }
+
+    @Bean
+    public TransactionTemplate transactionTemplateB(DataSourceTransactionManager transactionManagerB) {
+        return new TransactionTemplate(transactionManagerB);
+    }
+
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory2(DataSource dataSourceB) throws Exception {
+        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
+        mybatisSqlSessionFactoryBean.setDataSource(dataSourceB);
+        mybatisSqlSessionFactoryBean.setConfiguration(new MybatisConfiguration());
+        return mybatisSqlSessionFactoryBean.getObject();
+    }
+
+}

+ 67 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/MultiSqlSessionFactoryTest.java

@@ -0,0 +1,67 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory;
+
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.entity.AEntity;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.service.AEntityService;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.entity.BEntity;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.service.BEntityService;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.sql.DataSource;
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(classes = {AppConfig.class})
+public class MultiSqlSessionFactoryTest {
+
+    @Autowired
+    private AEntityService aEntityService;
+
+    @Autowired
+    private BEntityService bEntityService;
+
+    @Autowired
+    private DataSource dataSourceA;
+
+    @Autowired
+    private DataSource dataSourceB;
+
+    @Test
+    void test() throws Exception {
+        new SqlRunner(dataSourceA.getConnection()).run(
+            """
+                   CREATE TABLE IF NOT EXISTS  t_entity_a (
+                                           	id BIGINT NOT NULL AUTO_INCREMENT,
+                                           	name VARCHAR(30) NULL DEFAULT NULL ,
+                                           	PRIMARY KEY (id)
+                                           );
+                """
+        );
+
+        new SqlRunner(dataSourceB.getConnection()).run(
+            """
+                   CREATE TABLE IF NOT EXISTS  t_entity_b (
+                                           	id BIGINT NOT NULL AUTO_INCREMENT,
+                                           	name VARCHAR(30) NULL DEFAULT NULL ,
+                                           	PRIMARY KEY (id)
+                                           );
+                """
+        );
+        Assertions.assertEquals(0L, aEntityService.count());
+        Assertions.assertEquals(0L, bEntityService.count());
+        aEntityService.testSaveBath(List.of(new AEntity("test1"), new AEntity("test2")));
+        Assertions.assertEquals(2L, aEntityService.count());
+        bEntityService.testSaveBath(List.of(new BEntity("test1"), new BEntity("test2"), new BEntity("test3")));
+        Assertions.assertEquals(3L, bEntityService.count());
+
+    }
+
+}

+ 24 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/entity/AEntity.java

@@ -0,0 +1,24 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.a.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * @author nieqiurong
+ */
+@Data
+@TableName("t_entity_a")
+public class AEntity {
+
+    private Long id;
+
+    private String name;
+
+    public AEntity() {
+    }
+
+    public AEntity(String name) {
+        this.name = name;
+    }
+
+}

+ 13 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/mapper/AEntityMapper.java

@@ -0,0 +1,13 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.a.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.entity.AEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author nieqiurong
+ */
+@Mapper
+public interface AEntityMapper extends BaseMapper<AEntity> {
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/service/AEntityService.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.a.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.entity.AEntity;
+
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+public interface AEntityService extends IService<AEntity> {
+
+    void testSaveBath(List<AEntity> aEntityList);
+
+}

+ 32 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/a/service/impl/AEntityServiceImpl.java

@@ -0,0 +1,32 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.a.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.entity.AEntity;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.mapper.AEntityMapper;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.a.service.AEntityService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@Service
+public class AEntityServiceImpl extends ServiceImpl<AEntityMapper, AEntity> implements AEntityService {
+
+    @Autowired
+    protected TransactionTemplate transactionTemplateA;
+
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class, transactionManager = "transactionManagerA")
+    public void testSaveBath(List<AEntity> aEntityList) {
+        transactionTemplateA.execute((c) -> {
+            this.saveBatch(aEntityList);
+            return null;
+        });
+    }
+
+}

+ 24 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/entity/BEntity.java

@@ -0,0 +1,24 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.b.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * @author nieqiurong
+ */
+@Data
+@TableName("t_entity_b")
+public class BEntity {
+
+    private Long id;
+
+    private String name;
+
+    public BEntity() {
+    }
+
+    public BEntity(String name) {
+        this.name = name;
+    }
+
+}

+ 13 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/mapper/BEntityMapper.java

@@ -0,0 +1,13 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.b.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.entity.BEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author nieqiurong
+ */
+@Mapper
+public interface BEntityMapper extends BaseMapper<BEntity> {
+
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/service/BEntityService.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.b.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.entity.BEntity;
+
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+public interface BEntityService extends IService<BEntity> {
+
+    void testSaveBath(List<BEntity> bEntityList);
+
+}

+ 32 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/multisqlsessionfactory/b/service/impl/BEntityServiceImpl.java

@@ -0,0 +1,32 @@
+package com.baomidou.mybatisplus.test.multisqlsessionfactory.b.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.entity.BEntity;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.mapper.BEntityMapper;
+import com.baomidou.mybatisplus.test.multisqlsessionfactory.b.service.BEntityService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.util.List;
+
+/**
+ * @author nieqiurong
+ */
+@Service
+public class BEntityServiceImpl extends ServiceImpl<BEntityMapper, BEntity> implements BEntityService {
+
+    @Autowired
+    private TransactionTemplate transactionTemplateB;
+
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class, transactionManager = "transactionManagerB")
+    public void testSaveBath(List<BEntity> bEntityList) {
+        transactionTemplateB.execute((c) -> {
+            saveBatch(bEntityList);
+            return null;
+        });
+    }
+
+}