瀏覽代碼

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

achao 3 年之前
父節點
當前提交
a4b4f1cc7b
共有 50 個文件被更改,包括 907 次插入272 次删除
  1. 1 1
      build.gradle
  2. 4 0
      mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/DbType.java
  3. 3 2
      mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/SpringBootVFS.java
  4. 49 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisConfiguration.java
  5. 18 17
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperAnnotationBuilder.java
  6. 9 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperRegistry.java
  7. 2 1
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisXMLConfigBuilder.java
  8. 6 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractLambdaWrapper.java
  9. 14 13
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/AbstractMethod.java
  10. 15 3
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Delete.java
  11. 17 5
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/DeleteBatchByIds.java
  12. 17 5
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/DeleteById.java
  13. 15 3
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/DeleteByMap.java
  14. 15 3
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Insert.java
  15. 17 5
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectBatchByIds.java
  16. 17 5
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectById.java
  17. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectByMap.java
  18. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectCount.java
  19. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectList.java
  20. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectMaps.java
  21. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectMapsPage.java
  22. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectObjs.java
  23. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectOne.java
  24. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectPage.java
  25. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Update.java
  26. 14 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/UpdateById.java
  27. 9 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfoHelper.java
  28. 2 2
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/plugins/InterceptorIgnoreHelper.java
  29. 2 4
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ClassUtils.java
  30. 7 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ObjectUtils.java
  31. 8 12
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringUtils.java
  32. 6 8
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/TableNameParser.java
  33. 10 13
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/SqlInjectionUtils.java
  34. 2 1
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/ReflectLambdaMeta.java
  35. 2 1
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/ShadowLambdaMeta.java
  36. 38 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/incrementer/SapHanaKeyGenerator.java
  37. 24 11
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/AlwaysUpdateSomeColumnById.java
  38. 31 13
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/InsertBatchSomeColumn.java
  39. 14 7
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/LogicDeleteByIdWithFill.java
  40. 15 3
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/Upsert.java
  41. 3 2
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/BlockAttackInnerInterceptor.java
  42. 9 0
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameInnerInterceptor.java
  43. 174 65
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptor.java
  44. 2 1
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/DialectFactory.java
  45. 3 1
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/JdbcUtils.java
  46. 12 4
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SimpleQuery.java
  47. 1 1
      mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlHelper.java
  48. 168 26
      mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptorTest.java
  49. 5 9
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/toolkit/SimpleQueryTest.java
  50. 1 1
      settings.gradle

+ 1 - 1
build.gradle

@@ -11,7 +11,7 @@ ext {
     ]
 
     libraries = [
-        mybatisVersion = '3.5.7',
+        mybatisVersion = '3.5.8',
         mybatisSpringVersion = '2.0.6',
         mybatisSpringBootStarterVersion = '2.2.0',
         springVersion = '5.3.9',

+ 4 - 0
mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/DbType.java

@@ -135,6 +135,10 @@ public enum DbType {
      * CSIIDB
      */
     CSIIDB("csiidb", "CSIIDB数据库"),
+    /**
+     * CSIIDB
+     */
+    SAP_HANA("hana", "SAP_HANA数据库"),
     /**
      * UNKONWN DB
      */

+ 3 - 2
mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/SpringBootVFS.java

@@ -16,6 +16,7 @@
 package com.baomidou.mybatisplus.autoconfigure;
 
 
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import org.apache.ibatis.io.VFS;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@@ -49,7 +50,7 @@ public class SpringBootVFS extends VFS {
     private static String preserveSubpackageName(final String baseUrlString, final Resource resource,
                                                  final String rootPath) {
         try {
-            return rootPath + (rootPath.endsWith("/") ? "" : "/")
+            return rootPath + (rootPath.endsWith(StringPool.SLASH) ? StringPool.EMPTY : StringPool.SLASH)
                 + resource.getURL().toString().substring(baseUrlString.length());
         } catch (IOException e) {
             throw new UncheckedIOException(e);
@@ -59,7 +60,7 @@ public class SpringBootVFS extends VFS {
     @Override
     protected List<String> list(URL url, String path) throws IOException {
         String urlString = url.toString();
-        String baseUrlString = urlString.endsWith("/") ? urlString : urlString.concat("/");
+        String baseUrlString = urlString.endsWith(StringPool.SLASH) ? urlString : urlString.concat(StringPool.SLASH);
         Resource[] resources = resourceResolver.getResources(baseUrlString + "**/*.class");
         return Stream.of(resources).map(resource -> preserveSubpackageName(baseUrlString, resource, path))
             .collect(Collectors.toList());

+ 49 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisConfiguration.java

@@ -15,6 +15,11 @@
  */
 package com.baomidou.mybatisplus.core;
 
+import com.baomidou.mybatisplus.core.mapper.Mapper;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.ibatis.binding.MapperRegistry;
@@ -37,7 +42,9 @@ import org.apache.ibatis.transaction.Transaction;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.BiFunction;
+import java.util.stream.Collectors;
 
 /**
  * replace default Configuration class
@@ -119,6 +126,46 @@ public class MybatisConfiguration extends Configuration {
         mybatisMapperRegistry.addMapper(type);
     }
 
+    /**
+     * 新增注入新的 Mapper 信息,新增前会清理之前的缓存信息
+     *
+     * @param type Mapper Type
+     * @param <T>
+     */
+    public <T> void addNewMapper(Class<T> type) {
+        this.removeMapper(type);
+        this.addMapper(type);
+    }
+
+    /**
+     * 移除 Mapper 相关缓存,支持 GroovyClassLoader 动态注入 Mapper
+     *
+     * @param type Mapper Type
+     * @param <T>
+     */
+    public <T> void removeMapper(Class<T> type) {
+        // TODO
+        Set<String> mapperRegistryCache = GlobalConfigUtils.getGlobalConfig(this).getMapperRegistryCache();
+        final String mapperType = type.toString();
+        if (mapperRegistryCache.contains(mapperType)) {
+            // 清空实体表信息映射信息
+            TableInfoHelper.remove(ReflectionKit.getSuperClassGenericType(type, Mapper.class, 0));
+
+            // 清空 Mapper 缓存信息
+            this.mybatisMapperRegistry.removeMapper(type);
+            this.loadedResources.remove(type.toString());
+            mapperRegistryCache.remove(mapperType);
+
+            // 清空 Mapper 方法 mappedStatement 缓存信息
+            final String typeKey = type.getName() + StringPool.DOT;
+            Set<String> mapperSet = mappedStatements.entrySet().stream().filter(t -> t.getKey().startsWith(typeKey))
+                .map(t -> t.getKey()).collect(Collectors.toSet());
+            if (null != mapperSet && !mapperSet.isEmpty()) {
+                mapperSet.forEach(key -> mappedStatements.remove(key));
+            }
+        }
+    }
+
     /**
      * 使用自己的 MybatisMapperRegistry
      */
@@ -376,10 +423,10 @@ public class MybatisConfiguration extends Configuration {
         public V put(String key, V value) {
             if (containsKey(key)) {
                 throw new IllegalArgumentException(name + " already contains value for " + key
-                    + (conflictMessageProducer == null ? "" : conflictMessageProducer.apply(super.get(key), value)));
+                    + (conflictMessageProducer == null ? StringPool.EMPTY : conflictMessageProducer.apply(super.get(key), value)));
             }
             if (useGeneratedShortKey) {
-                if (key.contains(".")) {
+                if (key.contains(StringPool.DOT)) {
                     final String shortKey = getShortName(key);
                     if (super.get(shortKey) == null) {
                         super.put(shortKey, value);

+ 18 - 17
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperAnnotationBuilder.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.core;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.Getter;
 import org.apache.ibatis.annotations.*;
 import org.apache.ibatis.annotations.ResultMap;
@@ -80,7 +81,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
 
     public MybatisMapperAnnotationBuilder(Configuration configuration, Class<?> type) {
         super(configuration, type);
-        String resource = type.getName().replace('.', '/') + ".java (best guess)";
+        String resource = type.getName().replace(StringPool.DOT, StringPool.SLASH) + ".java (best guess)";
         this.assistant = new MapperBuilderAssistant(configuration, resource);
         this.configuration = configuration;
         this.type = type;
@@ -156,9 +157,9 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
         // to prevent loading again a resource twice
         // this flag is set at XMLMapperBuilder#bindMapperForNamespace
         if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
-            String xmlResource = type.getName().replace('.', '/') + ".xml";
+            String xmlResource = type.getName().replace(StringPool.DOT, StringPool.SLASH) + ".xml";
             // #1347
-            InputStream inputStream = type.getResourceAsStream("/" + xmlResource);
+            InputStream inputStream = type.getResourceAsStream(StringPool.SLASH + xmlResource);
             if (inputStream == null) {
                 // Search XML mapper that is not in the module but in the classpath.
                 try {
@@ -229,17 +230,17 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
     private String generateResultMapName(Method method) {
         Results results = method.getAnnotation(Results.class);
         if (results != null && !results.id().isEmpty()) {
-            return type.getName() + "." + results.id();
+            return type.getName() + StringPool.DOT + results.id();
         }
         StringBuilder suffix = new StringBuilder();
         for (Class<?> c : method.getParameterTypes()) {
-            suffix.append("-");
+            suffix.append(StringPool.DASH);
             suffix.append(c.getSimpleName());
         }
         if (suffix.length() < 1) {
             suffix.append("-void");
         }
-        return type.getName() + "." + method.getName() + suffix;
+        return type.getName() + StringPool.DOT + method.getName() + suffix;
     }
 
     private void applyResultMap(String resultMapId, Class<?> returnType, Arg[] args, Result[] results, TypeDiscriminator discriminator) {
@@ -255,7 +256,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
     private void createDiscriminatorResultMaps(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
         if (discriminator != null) {
             for (Case c : discriminator.cases()) {
-                String caseResultMapId = resultMapId + "-" + c.value();
+                String caseResultMapId = resultMapId + StringPool.DASH + c.value();
                 List<ResultMapping> resultMappings = new ArrayList<>();
                 // issue #136
                 applyConstructorArgs(c.constructArgs(), resultType, resultMappings);
@@ -278,7 +279,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
             Map<String, String> discriminatorMap = new HashMap<>();
             for (Case c : cases) {
                 String value = c.value();
-                String caseResultMapId = resultMapId + "-" + value;
+                String caseResultMapId = resultMapId + StringPool.DASH + value;
                 discriminatorMap.put(value, caseResultMapId);
             }
             return assistant.buildDiscriminator(resultType, column, javaType, jdbcType, typeHandler, discriminatorMap);
@@ -294,7 +295,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
             final SqlSource sqlSource = buildSqlSource(statementAnnotation.getAnnotation(), parameterTypeClass, languageDriver, method);
             final SqlCommandType sqlCommandType = statementAnnotation.getSqlCommandType();
             final Options options = getAnnotationWrapper(method, false, Options.class).map(x -> (Options) x.getAnnotation()).orElse(null);
-            final String mappedStatementId = type.getName() + "." + method.getName();
+            final String mappedStatementId = type.getName() + StringPool.DOT + method.getName();
 
             final KeyGenerator keyGenerator;
             String keyProperty = null;
@@ -342,7 +343,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
             if (isSelect) {
                 ResultMap resultMapAnnotation = method.getAnnotation(ResultMap.class);
                 if (resultMapAnnotation != null) {
-                    resultMapId = String.join(",", resultMapAnnotation.value());
+                    resultMapId = String.join(StringPool.COMMA, resultMapAnnotation.value());
                 } else {
                     resultMapId = generateResultMapName(method);
                 }
@@ -510,8 +511,8 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
         if (resultMapId.length() < 1) {
             resultMapId = result.many().resultMap();
         }
-        if (!resultMapId.contains(".")) {
-            resultMapId = type.getName() + "." + resultMapId;
+        if (!resultMapId.contains(StringPool.DOT)) {
+            resultMapId = type.getName() + StringPool.DOT + resultMapId;
         }
         return resultMapId;
     }
@@ -528,8 +529,8 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
         if (nestedSelect.length() < 1) {
             nestedSelect = result.many().select();
         }
-        if (!nestedSelect.contains(".")) {
-            nestedSelect = type.getName() + "." + nestedSelect;
+        if (!nestedSelect.contains(StringPool.DOT)) {
+            nestedSelect = type.getName() + StringPool.DOT + nestedSelect;
         }
         return nestedSelect;
     }
@@ -653,14 +654,14 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
             .collect(Collectors.toMap(AnnotationWrapper::getDatabaseId, x -> x, (existing, duplicate) -> {
                 throw new BuilderException(String.format("Detected conflicting annotations '%s' and '%s' on '%s'.",
                     existing.getAnnotation(), duplicate.getAnnotation(),
-                    method.getDeclaringClass().getName() + "." + method.getName()));
+                    method.getDeclaringClass().getName() + StringPool.DOT + method.getName()));
             }));
         AnnotationWrapper annotationWrapper = null;
         if (databaseId != null) {
             annotationWrapper = statementAnnotations.get(databaseId);
         }
         if (annotationWrapper == null) {
-            annotationWrapper = statementAnnotations.get("");
+            annotationWrapper = statementAnnotations.get(StringPool.EMPTY);
         }
         if (errorIfNoMatch && annotationWrapper == null && !statementAnnotations.isEmpty()) {
             // Annotations exist, but there is no matching one for the specified databaseId
@@ -711,7 +712,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
                 } else if (annotation instanceof SelectKey) {
                     databaseId = ((SelectKey) annotation).databaseId();
                 } else {
-                    databaseId = "";
+                    databaseId = StringPool.EMPTY;
                 }
             }
         }

+ 9 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperRegistry.java

@@ -62,6 +62,15 @@ public class MybatisMapperRegistry extends MapperRegistry {
         return knownMappers.containsKey(type);
     }
 
+    /**
+     * 清空 Mapper 缓存信息
+     */
+    protected <T> void removeMapper(Class<T> type) {
+        // TODO
+        knownMappers.entrySet().stream().filter(t -> t.getKey().getName().equals(type.getName()))
+            .findFirst().ifPresent(t -> knownMappers.remove(t.getKey()));
+    }
+
     @Override
     public <T> void addMapper(Class<T> type) {
         if (type.isInterface()) {

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

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.core;
 
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import org.apache.ibatis.builder.BaseBuilder;
 import org.apache.ibatis.builder.BuilderException;
 import org.apache.ibatis.builder.xml.XMLConfigBuilder;
@@ -142,7 +143,7 @@ public class MybatisXMLConfigBuilder extends BaseBuilder {
     private void loadCustomVfs(Properties props) throws ClassNotFoundException {
         String value = props.getProperty("vfsImpl");
         if (value != null) {
-            String[] clazzes = value.split(",");
+            String[] clazzes = value.split(StringPool.COMMA);
             for (String clazz : clazzes) {
                 if (!clazz.isEmpty()) {
                     @SuppressWarnings("unchecked")

+ 6 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractLambdaWrapper.java

@@ -51,7 +51,11 @@ public abstract class AbstractLambdaWrapper<T, Children extends AbstractLambdaWr
 
     @SafeVarargs
     protected final String columnsToString(boolean onlyColumn, SFunction<T, ?>... columns) {
-        return Arrays.stream(columns).map(i -> columnToString(i, onlyColumn)).collect(joining(StringPool.COMMA));
+        return columnsToString(onlyColumn, Arrays.asList(columns));
+    }
+
+    protected final String columnsToString(boolean onlyColumn, List<SFunction<T, ?>> columns) {
+        return columns.stream().map(i -> columnToString(i, onlyColumn)).collect(joining(StringPool.COMMA));
     }
 
     protected final String columnsToString(boolean onlyColumn, List<SFunction<T, ?>> columns) {
@@ -99,7 +103,7 @@ public abstract class AbstractLambdaWrapper<T, Children extends AbstractLambdaWr
     private ColumnCache getColumnCache(String fieldName, Class<?> lambdaClass) {
         ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName));
         Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]",
-                fieldName, lambdaClass.getName());
+            fieldName, lambdaClass.getName());
         return columnCache;
     }
 }

+ 14 - 13
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/AbstractMethod.java

@@ -15,9 +15,9 @@
  */
 package com.baomidou.mybatisplus.core.injector;
 
-import com.baomidou.mybatisplus.core.enums.SqlMethod;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
@@ -55,7 +55,18 @@ public abstract class AbstractMethod implements Constants {
     protected Configuration configuration;
     protected LanguageDriver languageDriver;
     protected MapperBuilderAssistant builderAssistant;
-
+    
+    /**
+     * 方法名称
+     * @since 3.4.4
+     */
+    protected final String name;
+    
+    protected AbstractMethod(String name) {
+        Assert.notNull(name,"方法名不能为空");
+        this.name = name;
+    }
+    
     /**
      * 注入自定义方法
      */
@@ -364,15 +375,5 @@ public abstract class AbstractMethod implements Constants {
      * @return MappedStatement
      */
     public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo);
-
-    /**
-     * 获取自定义方法名,未设置采用默认方法名
-     * https://gitee.com/baomidou/mybatis-plus/pulls/88
-     *
-     * @return method
-     * @author 义陆无忧
-     */
-    public String getMethod(SqlMethod sqlMethod) {
-        return sqlMethod.getMethod();
-    }
+    
 }

+ 15 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Delete.java

@@ -28,7 +28,19 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class Delete extends AbstractMethod {
-
+    
+    public Delete() {
+        super("delete");
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public Delete(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         String sql;
@@ -38,14 +50,14 @@ public class Delete extends AbstractMethod {
                 sqlWhereEntityWrapper(true, tableInfo),
                 sqlComment());
             SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-            return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+            return addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
         } else {
             sqlMethod = SqlMethod.DELETE;
             sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(),
                 sqlWhereEntityWrapper(true, tableInfo),
                 sqlComment());
             SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-            return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
+            return this.addDeleteMappedStatement(mapperClass, this.name, sqlSource);
         }
     }
 }

+ 17 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/DeleteBatchByIds.java

@@ -29,7 +29,19 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class DeleteBatchByIds extends AbstractMethod {
-
+    
+    public DeleteBatchByIds() {
+        super("deleteBatchIds");
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public DeleteBatchByIds(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         String sql;
@@ -42,8 +54,8 @@ public class DeleteBatchByIds extends AbstractMethod {
                         "#{item}", "#{item." + tableInfo.getKeyProperty() + "}"),
                     COLLECTION, null, "item", COMMA),
                 tableInfo.getLogicDeleteSql(true, true));
-            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
-            return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, tableInfo.getKeyType());
+            return addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
         } else {
             sqlMethod = SqlMethod.DELETE_BATCH_BY_IDS;
             sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),
@@ -51,8 +63,8 @@ public class DeleteBatchByIds extends AbstractMethod {
                     SqlScriptUtils.convertChoose("@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(item.getClass())",
                         "#{item}", "#{item." + tableInfo.getKeyProperty() + "}"),
                     COLLECTION, null, "item", COMMA));
-            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
-            return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
+            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, tableInfo.getKeyType());
+            return this.addDeleteMappedStatement(mapperClass, this.name, sqlSource);
         }
     }
 }

+ 17 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/DeleteById.java

@@ -36,7 +36,19 @@ import static java.util.stream.Collectors.toList;
  * @since 2018-04-06
  */
 public class DeleteById extends AbstractMethod {
-
+    
+    public DeleteById() {
+        super("deleteById");
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public DeleteById(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         String sql;
@@ -56,14 +68,14 @@ public class DeleteById extends AbstractMethod {
                     tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
                     tableInfo.getLogicDeleteSql(true, true));
             }
-            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
-            return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, tableInfo.getKeyType());
+            return addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
         } else {
             sqlMethod = SqlMethod.DELETE_BY_ID;
             sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),
                 tableInfo.getKeyProperty());
-            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
-            return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
+            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, tableInfo.getKeyType());
+            return this.addDeleteMappedStatement(mapperClass, this.name, sqlSource);
         }
     }
 }

+ 15 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/DeleteByMap.java

@@ -30,7 +30,19 @@ import java.util.Map;
  * @since 2018-04-06
  */
 public class DeleteByMap extends AbstractMethod {
-
+    
+    public DeleteByMap() {
+        super("deleteByMap");
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public DeleteByMap(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         String sql;
@@ -38,12 +50,12 @@ public class DeleteByMap extends AbstractMethod {
         if (tableInfo.isWithLogicDelete()) {
             sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo), sqlWhereByMap(tableInfo));
             SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
-            return addUpdateMappedStatement(mapperClass, Map.class, getMethod(sqlMethod), sqlSource);
+            return addUpdateMappedStatement(mapperClass, Map.class, this.name, sqlSource);
         } else {
             sqlMethod = SqlMethod.DELETE_BY_MAP;
             sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), this.sqlWhereByMap(tableInfo));
             SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
-            return this.addDeleteMappedStatement(mapperClass, getMethod(sqlMethod), sqlSource);
+            return this.addDeleteMappedStatement(mapperClass, this.name, sqlSource);
         }
     }
 }

+ 15 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Insert.java

@@ -36,7 +36,19 @@ import org.apache.ibatis.mapping.SqlSource;
  */
 @SuppressWarnings("serial")
 public class Insert extends AbstractMethod {
-
+    
+    public Insert() {
+        super(SqlMethod.INSERT_ONE.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public Insert(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
@@ -56,7 +68,7 @@ public class Insert extends AbstractMethod {
                 keyColumn = tableInfo.getKeyColumn();
             } else {
                 if (null != tableInfo.getKeySequence()) {
-                    keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
+                    keyGenerator = TableInfoHelper.genKeyGenerator(this.name, tableInfo, builderAssistant);
                     keyProperty = tableInfo.getKeyProperty();
                     keyColumn = tableInfo.getKeyColumn();
                 }
@@ -64,6 +76,6 @@ public class Insert extends AbstractMethod {
         }
         String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
+        return this.addInsertMappedStatement(mapperClass, modelClass, this.name, sqlSource, keyGenerator, keyProperty, keyColumn);
     }
 }

+ 17 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectBatchByIds.java

@@ -29,14 +29,26 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class SelectBatchByIds extends AbstractMethod {
-
+    
+    public SelectBatchByIds() {
+        super(SqlMethod.SELECT_BATCH_BY_IDS.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectBatchByIds(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_BATCH_BY_IDS;
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(),
-            sqlSelectColumns(tableInfo, false), tableInfo.getTableName(), tableInfo.getKeyColumn(),
-            SqlScriptUtils.convertForeach("#{item}", COLLECTION, null, "item", COMMA),
-            tableInfo.getLogicDeleteSql(true, true)), Object.class);
-        return addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
+                sqlSelectColumns(tableInfo, false), tableInfo.getTableName(), tableInfo.getKeyColumn(),
+                SqlScriptUtils.convertForeach("#{item}", COLLECTION, null, "item", COMMA),
+                tableInfo.getLogicDeleteSql(true, true)), tableInfo.getKeyType());
+        return addSelectMappedStatementForTable(mapperClass, this.name, sqlSource, tableInfo);
     }
 }

+ 17 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectById.java

@@ -29,14 +29,26 @@ import org.apache.ibatis.scripting.defaults.RawSqlSource;
  * @since 2018-04-06
  */
 public class SelectById extends AbstractMethod {
-
+    
+    public SelectById() {
+        super(SqlMethod.SELECT_BY_ID.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectById(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID;
         SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(),
-            sqlSelectColumns(tableInfo, false),
-            tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
-            tableInfo.getLogicDeleteSql(true, true)), Object.class);
-        return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
+                sqlSelectColumns(tableInfo, false),
+                tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
+                tableInfo.getLogicDeleteSql(true, true)), tableInfo.getKeyType());
+        return this.addSelectMappedStatementForTable(mapperClass, this.name, sqlSource, tableInfo);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectByMap.java

@@ -30,13 +30,25 @@ import java.util.Map;
  * @since 2018-04-06
  */
 public class SelectByMap extends AbstractMethod {
-
+    
+    public SelectByMap() {
+        super(SqlMethod.SELECT_BY_MAP.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectByMap(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_BY_MAP;
         String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, false),
             tableInfo.getTableName(), sqlWhereByMap(tableInfo));
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
-        return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
+        return this.addSelectMappedStatementForTable(mapperClass, this.name, sqlSource, tableInfo);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectCount.java

@@ -28,13 +28,25 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-08
  */
 public class SelectCount extends AbstractMethod {
-
+    
+    public SelectCount() {
+        super(SqlMethod.SELECT_COUNT.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectCount(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_COUNT;
         String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlCount(), tableInfo.getTableName(),
             sqlWhereEntityWrapper(true, tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addSelectMappedStatementForOther(mapperClass, getMethod(sqlMethod), sqlSource, Long.class);
+        return this.addSelectMappedStatementForOther(mapperClass, this.name, sqlSource, Long.class);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectList.java

@@ -28,13 +28,25 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class SelectList extends AbstractMethod {
-
+    
+    public SelectList() {
+        super(SqlMethod.SELECT_LIST.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectList(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_LIST;
         String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true), tableInfo.getTableName(),
             sqlWhereEntityWrapper(true, tableInfo), sqlOrderBy(tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
+        return this.addSelectMappedStatementForTable(mapperClass, this.name, sqlSource, tableInfo);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectMaps.java

@@ -30,13 +30,25 @@ import java.util.Map;
  * @since 2018-04-06
  */
 public class SelectMaps extends AbstractMethod {
-
+    
+    public SelectMaps() {
+        super(SqlMethod.SELECT_MAPS.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectMaps(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_MAPS;
         String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true), tableInfo.getTableName(),
             sqlWhereEntityWrapper(true, tableInfo),sqlOrderBy(tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addSelectMappedStatementForOther(mapperClass, getMethod(sqlMethod), sqlSource, Map.class);
+        return this.addSelectMappedStatementForOther(mapperClass, this.name, sqlSource, Map.class);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectMapsPage.java

@@ -30,13 +30,25 @@ import java.util.Map;
  * @since 2018-04-06
  */
 public class SelectMapsPage extends AbstractMethod {
-
+    
+    public SelectMapsPage() {
+        super(SqlMethod.SELECT_MAPS_PAGE.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectMapsPage(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_MAPS_PAGE;
         String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true),
             tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo), sqlOrderBy(tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addSelectMappedStatementForOther(mapperClass, getMethod(sqlMethod), sqlSource, Map.class);
+        return this.addSelectMappedStatementForOther(mapperClass, this.name, sqlSource, Map.class);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectObjs.java

@@ -28,13 +28,25 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class SelectObjs extends AbstractMethod {
-
+    
+    public SelectObjs() {
+        super(SqlMethod.SELECT_OBJS.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectObjs(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_OBJS;
         String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectObjsColumns(tableInfo),
             tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo),sqlOrderBy(tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addSelectMappedStatementForOther(mapperClass, getMethod(sqlMethod), sqlSource, Object.class);
+        return this.addSelectMappedStatementForOther(mapperClass, this.name, sqlSource, Object.class);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectOne.java

@@ -29,13 +29,25 @@ import org.apache.ibatis.mapping.SqlSource;
  */
 @Deprecated
 public class SelectOne extends AbstractMethod {
-
+    
+    public SelectOne() {
+        super(SqlMethod.SELECT_ONE.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public SelectOne(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_ONE;
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(),
             sqlFirst(), sqlSelectColumns(tableInfo, true), tableInfo.getTableName(),
             sqlWhereEntityWrapper(true, tableInfo), sqlComment()), modelClass);
-        return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
+        return this.addSelectMappedStatementForTable(mapperClass, this.name, sqlSource, tableInfo);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/SelectPage.java

@@ -28,13 +28,25 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class SelectPage extends AbstractMethod {
-
+    
+    public SelectPage() {
+        super(SqlMethod.SELECT_PAGE.getMethod());
+    }
+    
+    /**
+     * @since 3.4.4
+     * @param name 方法名
+     */
+    public SelectPage(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.SELECT_PAGE;
         String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true),
             tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo), sqlOrderBy(tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
+        return this.addSelectMappedStatementForTable(mapperClass, this.name, sqlSource, tableInfo);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Update.java

@@ -28,7 +28,19 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class Update extends AbstractMethod {
-
+    
+    public Update() {
+        super(SqlMethod.UPDATE.getMethod());
+    }
+    
+    /**
+     * @since 3.4.4
+     * @param name 方法名
+     */
+    public Update(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.UPDATE;
@@ -36,6 +48,6 @@ public class Update extends AbstractMethod {
             sqlSet(true, true, tableInfo, true, ENTITY, ENTITY_DOT),
             sqlWhereEntityWrapper(true, tableInfo), sqlComment());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+        return this.addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
     }
 }

+ 14 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/UpdateById.java

@@ -28,7 +28,19 @@ import org.apache.ibatis.mapping.SqlSource;
  * @since 2018-04-06
  */
 public class UpdateById extends AbstractMethod {
-
+    
+    public UpdateById() {
+        super(SqlMethod.UPDATE_BY_ID.getMethod());
+    }
+    
+    /**
+     * @since 3.4.4
+     * @param name 方法名
+     */
+    public UpdateById(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;
@@ -37,6 +49,6 @@ public class UpdateById extends AbstractMethod {
             sqlSet(tableInfo.isWithLogicDelete(), false, tableInfo, false, ENTITY, ENTITY_DOT),
             tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional);
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+        return addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
     }
 }

+ 9 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfoHelper.java

@@ -122,6 +122,15 @@ public class TableInfoHelper {
         return Collections.unmodifiableList(new ArrayList<>(TABLE_INFO_CACHE.values()));
     }
 
+    /**
+     * 清空实体表映射缓存信息
+     *
+     * @param entityClass 实体 Class
+     */
+    public static void remove(Class<?> entityClass) {
+        TABLE_INFO_CACHE.remove(entityClass);
+    }
+
     /**
      * <p>
      * 实体类反射获取表信息【初始化】

+ 2 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/plugins/InterceptorIgnoreHelper.java

@@ -147,10 +147,10 @@ public abstract class InterceptorIgnoreHelper {
         if (StringUtils.isBlank(value)) {
             return null;
         }
-        if ("1".equals(value) || "true".equals(value) || "on".equals(value)) {
+        if (StringPool.ONE.equals(value) || StringPool.TRUE.equals(value) || StringPool.ON.equals(value)) {
             return true;
         }
-        if ("0".equals(value) || "false".equals(value) || "off".equals(value)) {
+        if (StringPool.ZERO.equals(value) || StringPool.FALSE.equals(value) || StringPool.OFF.equals(value)) {
             return false;
         }
         throw ExceptionUtils.mpe("unsupported value \"%s\" by `@InterceptorIgnore#%s` on top of \"%s\"", value, node, name);

+ 2 - 4
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ClassUtils.java

@@ -43,8 +43,6 @@ public final class ClassUtils {
         }
     }
 
-    private static final char PACKAGE_SEPARATOR = '.';
-
     /**
      * 代理 class 的名称
      */
@@ -210,8 +208,8 @@ public final class ClassUtils {
      */
     public static String getPackageName(String fqClassName) {
         Assert.notNull(fqClassName, "Class name must not be null");
-        int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR);
-        return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : "");
+        int lastDotIndex = fqClassName.lastIndexOf(StringPool.DOT);
+        return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : StringPool.EMPTY);
     }
 
     /**

+ 7 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ObjectUtils.java

@@ -17,6 +17,7 @@ package com.baomidou.mybatisplus.core.toolkit;
 
 import java.lang.reflect.Array;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 
 /**
@@ -73,6 +74,12 @@ public class ObjectUtils {
         if (obj instanceof Map) {
             return ((Map<?, ?>) obj).isEmpty();
         }
+        if (obj instanceof Iterable) {
+            return !((Iterable<?>) obj).iterator().hasNext();
+        }
+        if (obj instanceof Iterator) {
+            return !((Iterator<?>) obj).hasNext();
+        }
         // else
         return false;
     }

+ 8 - 12
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringUtils.java

@@ -34,10 +34,6 @@ import static java.util.stream.Collectors.joining;
  */
 public final class StringUtils {
 
-    /**
-     * 空字符
-     */
-    public static final String EMPTY = StringPool.EMPTY;
     /**
      * 字符串 is
      */
@@ -154,7 +150,7 @@ public final class StringUtils {
      */
     public static String camelToUnderline(String param) {
         if (isBlank(param)) {
-            return EMPTY;
+            return StringPool.EMPTY;
         }
         int len = param.length();
         StringBuilder sb = new StringBuilder(len);
@@ -176,7 +172,7 @@ public final class StringUtils {
      */
     public static String underlineToCamel(String param) {
         if (isBlank(param)) {
-            return EMPTY;
+            return StringPool.EMPTY;
         }
         String temp = param.toLowerCase();
         int len = temp.length();
@@ -202,7 +198,7 @@ public final class StringUtils {
      */
     public static String firstToLowerCase(String param) {
         if (isBlank(param)) {
-            return EMPTY;
+            return StringPool.EMPTY;
         }
         return param.substring(0, 1).toLowerCase() + param.substring(1);
     }
@@ -313,7 +309,7 @@ public final class StringUtils {
      */
     public static String concatCapitalize(String concatStr, final String str) {
         if (isBlank(concatStr)) {
-            concatStr = EMPTY;
+            concatStr = StringPool.EMPTY;
         }
         if (str == null || str.length() == 0) {
             return str;
@@ -500,10 +496,10 @@ public final class StringUtils {
             if (lastOneIsNotUnderscore && (isUpperCaseAndPreviousIsLowerCase || previousIsWhitespace)) {
                 buf.append(StringPool.UNDERSCORE);
             } else if ((Character.isDigit(previousChar) && Character.isLetter(c))) {
-                buf.append('_');
+                buf.append(UNDERLINE);
             }
             if ((shouldReplace(c)) && (lastOneIsNotUnderscore)) {
-                buf.append('_');
+                buf.append(UNDERLINE);
             } else if (!Character.isWhitespace(c) && (isNotUnderscore || lastOneIsNotUnderscore)) {
                 buf.append(Character.toUpperCase(c));
             }
@@ -529,9 +525,9 @@ public final class StringUtils {
                 buf.append(StringPool.DASH);
             }
             if ('_' == c) {
-                buf.append('-');
+                buf.append(StringPool.DASH);
             } else if ('.' == c) {
-                buf.append('-');
+                buf.append(StringPool.DASH);
             } else if (!Character.isWhitespace(c)) {
                 buf.append(Character.toLowerCase(c));
             }

+ 6 - 8
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/TableNameParser.java

@@ -31,15 +31,13 @@ import java.util.regex.Pattern;
  * @since 2019-04-22
  */
 public final class TableNameParser {
-    private static final String TOKEN_GROUP_START = "(";
-    private static final String TOKEN_COMMA = ",";
+
     private static final String TOKEN_SET = "set";
     private static final String TOKEN_OF = "of";
     private static final String TOKEN_DUAL = "dual";
     private static final String TOKEN_DELETE = "delete";
     private static final String TOKEN_CREATE = "create";
     private static final String TOKEN_INDEX = "index";
-    private static final String TOKEN_ALL = "*";
 
     private static final String KEYWORD_JOIN = "join";
     private static final String KEYWORD_INTO = "into";
@@ -50,7 +48,7 @@ public final class TableNameParser {
     private static final String KEYWORD_DUPLICATE = "duplicate";
 
     private static final List<String> concerned = Arrays.asList(KEYWORD_TABLE, KEYWORD_INTO, KEYWORD_JOIN, KEYWORD_USING, KEYWORD_UPDATE);
-    private static final List<String> ignored = Arrays.asList(TOKEN_GROUP_START, TOKEN_SET, TOKEN_OF, TOKEN_DUAL);
+    private static final List<String> ignored = Arrays.asList(StringPool.LEFT_BRACKET, TOKEN_SET, TOKEN_OF, TOKEN_DUAL);
 
     /**
      * 该表达式会匹配 SQL 中不是 SQL TOKEN 的部分,比如换行符,注释信息,结尾的 {@code ;} 等。
@@ -154,7 +152,7 @@ public final class TableNameParser {
         if (TOKEN_DELETE.equalsIgnoreCase(current)) {
             if (hasMoreTokens(tokens, index++)) {
                 String next = tokens.get(index).getValue();
-                return !KEYWORD_FROM.equalsIgnoreCase(next) && !TOKEN_ALL.equals(next);
+                return !KEYWORD_FROM.equalsIgnoreCase(next) && !StringPool.ASTERISK.equals(next);
             }
         }
         return false;
@@ -214,7 +212,7 @@ public final class TableNameParser {
     }
 
     private static void processNonAliasedMultiTables(List<SqlToken> tokens, int index, String nextToken, TableNameVisitor visitor) {
-        while (nextToken.equals(TOKEN_COMMA)) {
+        while (nextToken.equals(StringPool.COMMA)) {
             visitNameToken(tokens.get(index++), visitor);
             if (hasMoreTokens(tokens, index)) {
                 nextToken = tokens.get(index++).getValue();
@@ -231,7 +229,7 @@ public final class TableNameParser {
         }
 
         if (shouldProcessMultipleTables(nextNextToken)) {
-            while (hasMoreTokens(tokens, index) && nextNextToken.equals(TOKEN_COMMA)) {
+            while (hasMoreTokens(tokens, index) && nextNextToken.equals(StringPool.COMMA)) {
                 if (hasMoreTokens(tokens, index)) {
                     current = tokens.get(index++);
                 }
@@ -247,7 +245,7 @@ public final class TableNameParser {
     }
 
     private static boolean shouldProcessMultipleTables(final String nextToken) {
-        return nextToken != null && nextToken.equals(TOKEN_COMMA);
+        return nextToken != null && nextToken.equals(StringPool.COMMA);
     }
 
     private static boolean hasMoreTokens(List<SqlToken> tokens, int index) {

+ 10 - 13
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/SqlInjectionUtils.java

@@ -25,11 +25,15 @@ import java.util.regex.Pattern;
  * @since 2021-08-15
  */
 public class SqlInjectionUtils {
-    // SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
-    private static final Pattern sqlSyntaxPattern = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" +
+    /**
+     * SQL语法检查正则:符合两个关键字(有先后顺序)才算匹配
+     */
+    private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" +
         ".+(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)", Pattern.CASE_INSENSITIVE);
-    // 使用'、;或注释截断SQL检查正则
-    private static final Pattern sqlCommentPattern = Pattern.compile("'.*(or|union|--|#|/*|;)", Pattern.CASE_INSENSITIVE);
+    /**
+     * 使用'、;或注释截断SQL检查正则
+     */
+    private static final Pattern SQL_COMMENT_PATTERN = Pattern.compile("'.*(or|union|--|#|/*|;)", Pattern.CASE_INSENSITIVE);
 
     /**
      * 检查参数是否存在 SQL 注入
@@ -39,14 +43,7 @@ public class SqlInjectionUtils {
      */
     public static boolean check(String value) {
         Objects.requireNonNull(value);
-        // 处理是否包含SQL注释字符
-        if (sqlCommentPattern.matcher(value).find()) {
-            return true;
-        }
-        // 检查是否包含SQL注入敏感字符
-        if (sqlSyntaxPattern.matcher(value).find()) {
-            return true;
-        }
-        return false;
+        // 处理是否包含SQL注释字符 || 检查是否包含SQL注入敏感字符
+        return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
     }
 }

+ 2 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/ReflectLambdaMeta.java

@@ -3,6 +3,7 @@ package com.baomidou.mybatisplus.core.toolkit.support;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
 import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.extern.slf4j.Slf4j;
 
 import java.lang.invoke.SerializedLambda;
@@ -42,7 +43,7 @@ public class ReflectLambdaMeta implements LambdaMeta {
     @Override
     public Class<?> getInstantiatedClass() {
         String instantiatedMethodType = lambda.getInstantiatedMethodType();
-        String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')).replace('/', '.');
+        String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(StringPool.SEMICOLON)).replace(StringPool.SLASH, StringPool.DOT);
         return ClassUtils.toClassConfident(instantiatedType, getCapturingClassClassLoader());
     }
 

+ 2 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/ShadowLambdaMeta.java

@@ -1,6 +1,7 @@
 package com.baomidou.mybatisplus.core.toolkit.support;
 
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 
 /**
  * 基于 {@link SerializedLambda} 创建的元信息
@@ -22,7 +23,7 @@ public class ShadowLambdaMeta implements LambdaMeta {
     @Override
     public Class<?> getInstantiatedClass() {
         String instantiatedMethodType = lambda.getInstantiatedMethodType();
-        String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')).replace('/', '.');
+        String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(StringPool.SEMICOLON)).replace(StringPool.SLASH, StringPool.DOT);
         return ClassUtils.toClassConfident(instantiatedType, lambda.getCapturingClass().getClassLoader());
     }
 

+ 38 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/incrementer/SapHanaKeyGenerator.java

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baomidou.mybatisplus.extension.incrementer;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
+
+/**
+ * SAP_HANA Key Sequence 生成器
+ *
+ * @author zhangchg
+ * @since 2021-12-03
+ */
+public class SapHanaKeyGenerator implements IKeyGenerator {
+
+    @Override
+    public String executeSql(String incrementerName) {
+        return "SELECT " + incrementerName + ".NEXTVAL FROM DUMMY";
+    }
+
+    @Override
+    public DbType dbType() {
+        return DbType.SAP_HANA;
+    }
+}

+ 24 - 11
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/AlwaysUpdateSomeColumnById.java

@@ -20,8 +20,6 @@ import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
-import lombok.AllArgsConstructor;
-import lombok.NoArgsConstructor;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import org.apache.ibatis.mapping.MappedStatement;
@@ -44,8 +42,6 @@ import java.util.function.Predicate;
  * @author hubin
  * @since 2019-04-12
  */
-@NoArgsConstructor
-@AllArgsConstructor
 @SuppressWarnings("serial")
 public class AlwaysUpdateSomeColumnById extends AbstractMethod {
 
@@ -55,7 +51,29 @@ public class AlwaysUpdateSomeColumnById extends AbstractMethod {
     @Setter
     @Accessors(chain = true)
     private Predicate<TableFieldInfo> predicate;
-
+    
+    /**
+     * @param name      方法名
+     * @param predicate 筛选条件
+     * @since 3.4.4
+     */
+    public AlwaysUpdateSomeColumnById(String name, Predicate<TableFieldInfo> predicate) {
+        super(name);
+        this.predicate = predicate;
+    }
+    
+    public AlwaysUpdateSomeColumnById() {
+        super("alwaysUpdateSomeColumnById");
+    }
+    
+    /**
+     * @param predicate 筛选条件
+     */
+    public AlwaysUpdateSomeColumnById(Predicate<TableFieldInfo> predicate) {
+        super("alwaysUpdateSomeColumnById");
+        this.predicate = predicate;
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;
@@ -66,7 +84,7 @@ public class AlwaysUpdateSomeColumnById extends AbstractMethod {
         String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet,
             tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional);
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+        return addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
     }
 
     private Predicate<TableFieldInfo> getPredicate() {
@@ -77,9 +95,4 @@ public class AlwaysUpdateSomeColumnById extends AbstractMethod {
         return noLogic;
     }
 
-    @Override
-    public String getMethod(SqlMethod sqlMethod) {
-        // 自定义 mapper 方法名
-        return "alwaysUpdateSomeColumnById";
-    }
 }

+ 31 - 13
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/InsertBatchSomeColumn.java

@@ -22,8 +22,6 @@ import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
-import lombok.AllArgsConstructor;
-import lombok.NoArgsConstructor;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
@@ -61,18 +59,43 @@ import java.util.function.Predicate;
  * @since 2018-11-29
  */
 
-@NoArgsConstructor
-@AllArgsConstructor
 @SuppressWarnings("serial")
 public class InsertBatchSomeColumn extends AbstractMethod {
-
+    
     /**
      * 字段筛选条件
      */
     @Setter
     @Accessors(chain = true)
     private Predicate<TableFieldInfo> predicate;
-
+    
+    /**
+     * 默认方法名
+     */
+    public InsertBatchSomeColumn() {
+        super("insertBatchSomeColumn");
+    }
+    
+    /**
+     * 默认方法名
+     *
+     * @param predicate 字段筛选条件
+     */
+    public InsertBatchSomeColumn(Predicate<TableFieldInfo> predicate) {
+        super("insertBatchSomeColumn");
+        this.predicate = predicate;
+    }
+    
+    /**
+     * @param name      方法名
+     * @param predicate 字段筛选条件
+     * @since 3.4.4
+     */
+    public InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate) {
+        super(name);
+        this.predicate = predicate;
+    }
+    
     @SuppressWarnings("Duplicates")
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
@@ -97,7 +120,7 @@ public class InsertBatchSomeColumn extends AbstractMethod {
                 keyColumn = tableInfo.getKeyColumn();
             } else {
                 if (null != tableInfo.getKeySequence()) {
-                    keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
+                    keyGenerator = TableInfoHelper.genKeyGenerator(this.name, tableInfo, builderAssistant);
                     keyProperty = tableInfo.getKeyProperty();
                     keyColumn = tableInfo.getKeyColumn();
                 }
@@ -105,12 +128,7 @@ public class InsertBatchSomeColumn extends AbstractMethod {
         }
         String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
+        return this.addInsertMappedStatement(mapperClass, modelClass, this.name, sqlSource, keyGenerator, keyProperty, keyColumn);
     }
 
-    @Override
-    public String getMethod(SqlMethod sqlMethod) {
-        // 自定义 mapper 方法名
-        return "insertBatchSomeColumn";
-    }
 }

+ 14 - 7
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/LogicDeleteByIdWithFill.java

@@ -45,7 +45,19 @@ import static java.util.stream.Collectors.toList;
 @SuppressWarnings("serial")
 @Deprecated
 public class LogicDeleteByIdWithFill extends AbstractMethod {
-
+    
+    public LogicDeleteByIdWithFill() {
+        super("deleteByIdWithFill");
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public LogicDeleteByIdWithFill(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         String sql;
@@ -70,12 +82,7 @@ public class LogicDeleteByIdWithFill extends AbstractMethod {
                 tableInfo.getKeyProperty());
         }
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return addUpdateMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource);
+        return addUpdateMappedStatement(mapperClass, modelClass, this.name, sqlSource);
     }
 
-    @Override
-    public String getMethod(SqlMethod sqlMethod) {
-        // 自定义 mapper 方法名
-        return "deleteByIdWithFill";
-    }
 }

+ 15 - 3
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/Upsert.java

@@ -33,7 +33,19 @@ import org.apache.ibatis.mapping.SqlSource;
  */
 @SuppressWarnings("serial")
 public class Upsert extends AbstractMethod {
-
+    
+    public Upsert() {
+        super(SqlMethod.UPSERT_ONE.getMethod());
+    }
+    
+    /**
+     * @param name 方法名
+     * @since 3.4.4
+     */
+    public Upsert(String name) {
+        super(name);
+    }
+    
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
@@ -48,13 +60,13 @@ public class Upsert extends AbstractMethod {
         if (tableInfo.havePK()) {
             // 自增主键会造成HBase单Region数据挤压,直接移除
             if (null != tableInfo.getKeySequence()) {
-                keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
+                keyGenerator = TableInfoHelper.genKeyGenerator(this.name, tableInfo, builderAssistant);
                 keyProperty = tableInfo.getKeyProperty();
                 keyColumn = tableInfo.getKeyColumn();
             }
         }
         String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
+        return this.addInsertMappedStatement(mapperClass, modelClass, this.name, sqlSource, keyGenerator, keyProperty, keyColumn);
     }
 }

+ 3 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/BlockAttackInnerInterceptor.java

@@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
 import net.sf.jsqlparser.expression.BinaryExpression;
@@ -127,12 +128,12 @@ public class BlockAttackInnerInterceptor extends JsqlParserSupport implements In
      */
     private String getTableLogicField(String tableName) {
         if (StringUtils.isBlank(tableName)) {
-            return StringUtils.EMPTY;
+            return StringPool.EMPTY;
         }
 
         TableInfo tableInfo = TableInfoHelper.getTableInfo(tableName);
         if (tableInfo == null || !tableInfo.isWithLogicDelete() || tableInfo.getLogicDeleteFieldInfo() == null) {
-            return StringUtils.EMPTY;
+            return StringPool.EMPTY;
         }
         return tableInfo.getLogicDeleteFieldInfo().getColumn();
     }

+ 9 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameInnerInterceptor.java

@@ -49,6 +49,12 @@ import java.util.List;
 @AllArgsConstructor
 @SuppressWarnings({"rawtypes"})
 public class DynamicTableNameInnerInterceptor implements InnerInterceptor {
+    private Runnable hook;
+
+    public void setHook(Runnable hook) {
+        this.hook = hook;
+    }
+    
     /**
      * 表名处理器,是否处理表名的情况都在该处理器中自行判断
      */
@@ -90,6 +96,9 @@ public class DynamicTableNameInnerInterceptor implements InnerInterceptor {
         }
         if (last != sql.length()) {
             builder.append(sql.substring(last));
+        }
+         if(hook != null){
+            hook.run();
         }
         return builder.toString();
     }

+ 174 - 65
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptor.java

@@ -41,7 +41,10 @@ import org.apache.ibatis.session.RowBounds;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
@@ -234,27 +237,55 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
      * 处理 PlainSelect
      */
     protected void processPlainSelect(PlainSelect plainSelect) {
-        FromItem fromItem = plainSelect.getFromItem();
-        Expression where = plainSelect.getWhere();
-        processWhereSubSelect(where);
-        if (fromItem instanceof Table) {
-            Table fromTable = (Table) fromItem;
-            if (!tenantLineHandler.ignoreTable(fromTable.getName())) {
-                //#1186 github
-                plainSelect.setWhere(builderExpression(where, fromTable));
-            }
-        } else {
-            processFromItem(fromItem);
-        }
         //#3087 github
         List<SelectItem> selectItems = plainSelect.getSelectItems();
         if (CollectionUtils.isNotEmpty(selectItems)) {
             selectItems.forEach(this::processSelectItem);
         }
+
+        // 处理 where 中的子查询
+        Expression where = plainSelect.getWhere();
+        processWhereSubSelect(where);
+
+        // 处理 fromItem
+        FromItem fromItem = plainSelect.getFromItem();
+        List<Table> list = processFromItem(fromItem);
+        List<Table> mainTables = new ArrayList<>(list);
+
+        // 处理 join
         List<Join> joins = plainSelect.getJoins();
         if (CollectionUtils.isNotEmpty(joins)) {
-            processJoins(joins);
+            mainTables = processJoins(mainTables, joins);
+        }
+
+        // 当有 mainTable 时,进行 where 条件追加
+        if (CollectionUtils.isNotEmpty(mainTables)) {
+            plainSelect.setWhere(builderExpression(where, mainTables));
+        }
+    }
+
+    private List<Table> processFromItem(FromItem fromItem) {
+        // 处理括号括起来的表达式
+        while (fromItem instanceof ParenthesisFromItem) {
+            fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
+        }
+
+        List<Table> mainTables = new ArrayList<>();
+        // 无 join 时的处理逻辑
+        if (fromItem instanceof Table) {
+            Table fromTable = (Table) fromItem;
+            if (!tenantLineHandler.ignoreTable(fromTable.getName())) {
+                mainTables.add(fromTable);
+            }
+        } else if (fromItem instanceof SubJoin) {
+            // SubJoin 类型则还需要添加上 where 条件
+            List<Table> tables = processSubJoin((SubJoin) fromItem);
+            mainTables.addAll(tables);
+        } else {
+            // 处理下 fromItem
+            processOtherFromItem(fromItem);
         }
+        return mainTables;
     }
 
     /**
@@ -282,7 +313,7 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
             return;
         }
         if (where instanceof FromItem) {
-            processFromItem((FromItem) where);
+            processOtherFromItem((FromItem) where);
             return;
         }
         if (where.toString().indexOf("SELECT") > 0) {
@@ -348,16 +379,13 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
     /**
      * 处理子查询等
      */
-    protected void processFromItem(FromItem fromItem) {
-        if (fromItem instanceof SubJoin) {
-            SubJoin subJoin = (SubJoin) fromItem;
-            if (subJoin.getJoinList() != null) {
-                processJoins(subJoin.getJoinList());
-            }
-            if (subJoin.getLeft() != null) {
-                processFromItem(subJoin.getLeft());
-            }
-        } else if (fromItem instanceof SubSelect) {
+    protected void processOtherFromItem(FromItem fromItem) {
+        // 去除括号
+        while (fromItem instanceof ParenthesisFromItem) {
+            fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
+        }
+
+        if (fromItem instanceof SubSelect) {
             SubSelect subSelect = (SubSelect) fromItem;
             if (subSelect.getSelectBody() != null) {
                 processSelectBody(subSelect.getSelectBody());
@@ -375,82 +403,160 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
         }
     }
 
+    /**
+     * 处理 sub join
+     *
+     * @param subJoin subJoin
+     * @return Table subJoin 中的主表
+     */
+    private List<Table> processSubJoin(SubJoin subJoin) {
+        List<Table> mainTables = new ArrayList<>();
+        if (subJoin.getJoinList() != null) {
+            List<Table> list = processFromItem(subJoin.getLeft());
+            mainTables.addAll(list);
+            mainTables = processJoins(mainTables, subJoin.getJoinList());
+        }
+        return mainTables;
+    }
+
     /**
      * 处理 joins
      *
-     * @param joins join 集合
+     * @param mainTables 可以为 null
+     * @param joins      join 集合
+     * @return List<Table> 右连接查询的 Table 列表
      */
-    private void processJoins(List<Join> joins) {
+    private List<Table> processJoins(List<Table> mainTables, List<Join> joins) {
+        if (mainTables == null) {
+            mainTables = new ArrayList<>();
+        }
+
+        // join 表达式中最终的主表
+        Table mainTable = null;
+        // 当前 join 的左表
+        Table leftTable = null;
+        if (mainTables.size() == 1) {
+            mainTable = mainTables.get(0);
+            leftTable = mainTable;
+        }
+
         //对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名
-        Deque<Table> tables = new LinkedList<>();
+        Deque<List<Table>> onTableDeque = new LinkedList<>();
         for (Join join : joins) {
             // 处理 on 表达式
-            FromItem fromItem = join.getRightItem();
-            if (fromItem instanceof Table) {
-                Table fromTable = (Table) fromItem;
+            FromItem joinItem = join.getRightItem();
+
+            // 获取当前 join 的表,subJoint 可以看作是一张表
+            List<Table> joinTables = null;
+            if (joinItem instanceof Table) {
+                joinTables = new ArrayList<>();
+                joinTables.add((Table) joinItem);
+            } else if (joinItem instanceof SubJoin) {
+                joinTables = processSubJoin((SubJoin) joinItem);
+            }
+
+            if (joinTables != null) {
+
+                // 如果是隐式内连接
+                if (join.isSimple()) {
+                    mainTables.addAll(joinTables);
+                    continue;
+                }
+
+                // 当前表是否忽略
+                Table joinTable = joinTables.get(0);
+                boolean joinTableNeedIgnore = tenantLineHandler.ignoreTable(joinTable.getName());
+
+                List<Table> onTables = null;
+                // 如果不要忽略,且是右连接,则记录下当前表
+                if (join.isRight()) {
+                    mainTable = joinTableNeedIgnore ? null : joinTable;
+                    if (leftTable != null) {
+                        onTables = Collections.singletonList(leftTable);
+                    }
+                } else if (join.isLeft()) {
+                    if (!joinTableNeedIgnore) {
+                        onTables = Collections.singletonList(joinTable);
+                    }
+                } else if (join.isInner()) {
+                    if (mainTable == null) {
+                        onTables = Collections.singletonList(joinTable);
+                    } else {
+                        onTables = Arrays.asList(mainTable, joinTable);
+                    }
+                    mainTable = null;
+                }
+                mainTables = new ArrayList<>();
+                if (mainTable != null) {
+                    mainTables.add(mainTable);
+                }
+
                 // 获取 join 尾缀的 on 表达式列表
                 Collection<Expression> originOnExpressions = join.getOnExpressions();
                 // 正常 join on 表达式只有一个,立刻处理
-                if (originOnExpressions.size() == 1) {
-                    processJoin(join);
+                if (originOnExpressions.size() == 1 && onTables != null) {
+                    List<Expression> onExpressions = new LinkedList<>();
+                    onExpressions.add(builderExpression(originOnExpressions.iterator().next(), onTables));
+                    join.setOnExpressions(onExpressions);
+                    leftTable = joinTable;
                     continue;
                 }
-                // 当前表是否忽略
-                boolean needIgnore = tenantLineHandler.ignoreTable(fromTable.getName());
                 // 表名压栈,忽略的表压入 null,以便后续不处理
-                tables.push(needIgnore ? null : fromTable);
+                onTableDeque.push(onTables);
                 // 尾缀多个 on 表达式的时候统一处理
                 if (originOnExpressions.size() > 1) {
                     Collection<Expression> onExpressions = new LinkedList<>();
                     for (Expression originOnExpression : originOnExpressions) {
-                        Table currentTable = tables.poll();
-                        if (currentTable == null) {
+                        List<Table> currentTableList = onTableDeque.poll();
+                        if (CollectionUtils.isEmpty(currentTableList)) {
                             onExpressions.add(originOnExpression);
                         } else {
-                            onExpressions.add(builderExpression(originOnExpression, currentTable));
+                            onExpressions.add(builderExpression(originOnExpression, currentTableList));
                         }
                     }
                     join.setOnExpressions(onExpressions);
                 }
+                leftTable = joinTable;
             } else {
-                // 处理右边连接的子表达式
-                processFromItem(fromItem);
+                processOtherFromItem(joinItem);
+                leftTable = null;
             }
+
         }
+
+        return mainTables;
     }
 
     /**
-     * 处理联接语句
+     * 处理条件
      */
-    protected void processJoin(Join join) {
-        if (join.getRightItem() instanceof Table) {
-            Table fromTable = (Table) join.getRightItem();
-            if (tenantLineHandler.ignoreTable(fromTable.getName())) {
-                // 过滤退出执行
-                return;
+    protected Expression builderExpression(Expression currentExpression, List<Table> tables) {
+        // 没有表需要处理直接返回
+        if (CollectionUtils.isEmpty(tables)) {
+            return currentExpression;
+        }
+        // 租户
+        Expression tenantId = tenantLineHandler.getTenantId();
+        // 构造每张表的条件
+        List<EqualsTo> equalsTos = tables.stream()
+            .map(item -> new EqualsTo(getAliasColumn(item), tenantId))
+            .collect(Collectors.toList());
+        // 注入的表达式
+        Expression injectExpression = equalsTos.get(0);
+        // 如果有多表,则用 and 连接
+        if (equalsTos.size() > 1) {
+            for (int i = 1; i < equalsTos.size(); i++) {
+                injectExpression = new AndExpression(injectExpression, equalsTos.get(i));
             }
-            // 走到这里说明 on 表达式肯定只有一个
-            Collection<Expression> originOnExpressions = join.getOnExpressions();
-            List<Expression> onExpressions = new LinkedList<>();
-            onExpressions.add(builderExpression(originOnExpressions.iterator().next(), fromTable));
-            join.setOnExpressions(onExpressions);
         }
-    }
 
-    /**
-     * 处理条件
-     */
-    protected Expression builderExpression(Expression currentExpression, Table table) {
-        EqualsTo equalsTo = new EqualsTo();
-        equalsTo.setLeftExpression(this.getAliasColumn(table));
-        equalsTo.setRightExpression(tenantLineHandler.getTenantId());
         if (currentExpression == null) {
-            return equalsTo;
+            return injectExpression;
         }
         if (currentExpression instanceof OrExpression) {
-            return new AndExpression(new Parenthesis(currentExpression), equalsTo);
+            return new AndExpression(new Parenthesis(currentExpression), injectExpression);
         } else {
-            return new AndExpression(currentExpression, equalsTo);
+            return new AndExpression(currentExpression, injectExpression);
         }
     }
 
@@ -463,10 +569,13 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
      */
     protected Column getAliasColumn(Table table) {
         StringBuilder column = new StringBuilder();
+        // 为了兼容隐式内连接,没有别名时条件就需要加上表名
         if (table.getAlias() != null) {
-            column.append(table.getAlias().getName()).append(StringPool.DOT);
+            column.append(table.getAlias().getName());
+        } else {
+            column.append(table.getName());
         }
-        column.append(tenantLineHandler.getTenantIdColumn());
+        column.append(StringPool.DOT).append(tenantLineHandler.getTenantIdColumn());
         return new Column(column.toString());
     }
 

+ 2 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/DialectFactory.java

@@ -62,7 +62,8 @@ public class DialectFactory {
                 || dbType == DbType.SQLITE
                 || dbType == DbType.HSQL
                 || dbType == DbType.KINGBASE_ES
-                || dbType == DbType.PHOENIX) {
+                || dbType == DbType.PHOENIX
+                || dbType == DbType.SAP_HANA) {
                 dialect = new PostgreDialect();
             } else if (dbType == DbType.HIGH_GO) {
                 dialect = new HighGoDialect();

+ 3 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/JdbcUtils.java

@@ -111,7 +111,9 @@ public class JdbcUtils {
             return DbType.GOLDILOCKS;
         } else if (url.contains(":csiidb:")) {
             return DbType.CSIIDB;
-        } else {
+        } else if (url.contains(":sap:")) {
+            return DbType.SAP_HANA;
+        }else {
             logger.warn("The jdbcUrl is " + jdbcUrl + ", Mybatis Plus Cannot Read Database type or The Database's Not Supported!");
             return DbType.OTHER;
         }

+ 12 - 4
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SimpleQuery.java

@@ -4,8 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -124,7 +123,16 @@ public class SimpleQuery {
      */
     @SafeVarargs
     public static <A, E> Map<A, List<E>> listGroupBy(List<E> list, SFunction<E, A> sFunction, Consumer<E>... peeks) {
-        return Stream.of(peeks).reduce(list.parallelStream(), Stream::peek, Stream::concat).collect(Collectors.groupingBy(sFunction));
+        return Stream.of(peeks).reduce(list.parallelStream(), Stream::peek, Stream::concat).collect(HashMap::new, (m, v) -> {
+            A key = Optional.ofNullable(v).map(sFunction).orElse(null);
+            List<E> values = m.getOrDefault(key, new ArrayList<>(list.size()));
+            values.add(v);
+            m.put(key, values);
+        }, (totalMap, nowMap) -> nowMap.forEach((k, v) -> {
+            List<E> values = totalMap.getOrDefault(k, new ArrayList<>(list.size()));
+            values.addAll(v);
+            totalMap.put(k, values);
+        }));
     }
 
 
@@ -141,7 +149,7 @@ public class SimpleQuery {
      */
     @SafeVarargs
     public static <E, A, P> Map<A, P> list2Map(List<E> list, SFunction<E, A> keyFunc, Function<E, P> valueFunc, Consumer<E>... peeks) {
-        return Stream.of(peeks).reduce(list.parallelStream(), Stream::peek, Stream::concat).collect(Collectors.toMap(keyFunc, valueFunc, (l, r) -> l));
+        return Stream.of(peeks).reduce(list.parallelStream(), Stream::peek, Stream::concat).collect(HashMap::new, (m, v) -> m.put(keyFunc.apply(v), valueFunc.apply(v)), HashMap::putAll);
     }
 
 

+ 1 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlHelper.java

@@ -180,7 +180,7 @@ public final class SqlHelper {
         }
         try {
             consumer.accept(sqlSession);
-            //非事情况下,强制commit。
+            //非事情况下,强制commit。
             sqlSession.commit(!transaction);
             return true;
         } catch (Throwable t) {

+ 168 - 26
mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptorTest.java

@@ -38,48 +38,48 @@ class TenantLineInnerInterceptorTest {
             "INSERT INTO entity (id, name, tenant_id) VALUES (?, ?, ?)");
         // insert into select
         assertSql("insert into entity (id,name) select id,name from entity2",
-            "INSERT INTO entity (id, name, tenant_id) SELECT id, name, tenant_id FROM entity2 WHERE tenant_id = 1");
+            "INSERT INTO entity (id, name, tenant_id) SELECT id, name, tenant_id FROM entity2 WHERE entity2.tenant_id = 1");
 
         assertSql("insert into entity (id,name) select * from entity2",
-            "INSERT INTO entity (id, name, tenant_id) SELECT * FROM entity2 WHERE tenant_id = 1");
+            "INSERT INTO entity (id, name, tenant_id) SELECT * FROM entity2 WHERE entity2.tenant_id = 1");
 
         assertSql("insert into entity (id,name) select id,name from (select id,name from entity3) t",
-            "INSERT INTO entity (id, name, tenant_id) SELECT id, name, tenant_id FROM (SELECT id, name, tenant_id FROM entity3 WHERE tenant_id = 1) t");
+            "INSERT INTO entity (id, name, tenant_id) SELECT id, name, tenant_id FROM (SELECT id, name, tenant_id FROM entity3 WHERE entity3.tenant_id = 1) t");
 
         assertSql("insert into entity (id,name) select * from (select id,name from entity3) t",
-            "INSERT INTO entity (id, name, tenant_id) SELECT * FROM (SELECT id, name, tenant_id FROM entity3 WHERE tenant_id = 1) t");
+            "INSERT INTO entity (id, name, tenant_id) SELECT * FROM (SELECT id, name, tenant_id FROM entity3 WHERE entity3.tenant_id = 1) t");
 
         assertSql("insert into entity (id,name) select t.* from (select id,name from entity3) t",
-            "INSERT INTO entity (id, name, tenant_id) SELECT t.* FROM (SELECT id, name, tenant_id FROM entity3 WHERE tenant_id = 1) t");
+            "INSERT INTO entity (id, name, tenant_id) SELECT t.* FROM (SELECT id, name, tenant_id FROM entity3 WHERE entity3.tenant_id = 1) t");
     }
 
     @Test
     void delete() {
         assertSql("delete from entity where id = ?",
-            "DELETE FROM entity WHERE tenant_id = 1 AND id = ?");
+            "DELETE FROM entity WHERE entity.tenant_id = 1 AND id = ?");
     }
 
     @Test
     void update() {
         assertSql("update entity set name = ? where id = ?",
-            "UPDATE entity SET name = ? WHERE tenant_id = 1 AND id = ?");
+            "UPDATE entity SET name = ? WHERE entity.tenant_id = 1 AND id = ?");
     }
 
     @Test
     void selectSingle() {
         // 单表
         assertSql("select * from entity where id = ?",
-            "SELECT * FROM entity WHERE id = ? AND tenant_id = 1");
+            "SELECT * FROM entity WHERE id = ? AND entity.tenant_id = 1");
 
         assertSql("select * from entity where id = ? or name = ?",
-            "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1");
+            "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
 
         assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)",
-            "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1");
+            "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
 
         /* not */
         assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)",
-            "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1");
+            "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND entity.tenant_id = 1");
     }
 
     @Test
@@ -178,6 +178,14 @@ class TenantLineInnerInterceptorTest {
             "SELECT * FROM entity e " +
                 "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
                 "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+
+        assertSql("SELECT * FROM entity e " +
+                "left join entity1 e1 on e1.id = e.id " +
+                "left join entity2 e2 on e1.id = e2.id",
+            "SELECT * FROM entity e " +
+                "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
+                "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
+                "WHERE e.tenant_id = 1");
     }
 
     @Test
@@ -186,17 +194,125 @@ class TenantLineInnerInterceptorTest {
         assertSql("SELECT * FROM entity e " +
                 "right join entity1 e1 on e1.id = e.id",
             "SELECT * FROM entity e " +
-                "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                "WHERE e.tenant_id = 1");
+                "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+                "WHERE e1.tenant_id = 1");
+
+        assertSql("SELECT * FROM with_as_1 e " +
+                "right join entity1 e1 on e1.id = e.id",
+            "SELECT * FROM with_as_1 e " +
+                "RIGHT JOIN entity1 e1 ON e1.id = e.id " +
+                "WHERE e1.tenant_id = 1");
 
         assertSql("SELECT * FROM entity e " +
                 "right join entity1 e1 on e1.id = e.id " +
                 "WHERE e.id = ? OR e.name = ?",
             "SELECT * FROM entity e " +
-                "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+                "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+                "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
+
+        assertSql("SELECT * FROM entity e " +
+                "right join entity1 e1 on e1.id = e.id " +
+                "right join entity2 e2 on e1.id = e2.id ",
+            "SELECT * FROM entity e " +
+                "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+                "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
+                "WHERE e2.tenant_id = 1");
     }
 
+    @Test
+    void selectMixJoin() {
+        assertSql("SELECT * FROM entity e " +
+                "right join entity1 e1 on e1.id = e.id " +
+                "left join entity2 e2 on e1.id = e2.id",
+            "SELECT * FROM entity e " +
+                "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
+                "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
+                "WHERE e1.tenant_id = 1");
+
+        assertSql("SELECT * FROM entity e " +
+                "left join entity1 e1 on e1.id = e.id " +
+                "right join entity2 e2 on e1.id = e2.id",
+            "SELECT * FROM entity e " +
+                "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
+                "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
+                "WHERE e2.tenant_id = 1");
+
+        assertSql("SELECT * FROM entity e " +
+                "left join entity1 e1 on e1.id = e.id " +
+                "inner join entity2 e2 on e1.id = e2.id",
+            "SELECT * FROM entity e " +
+                "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
+                "INNER JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 AND e2.tenant_id = 1");
+    }
+
+
+    @Test
+    void selectJoinSubSelect() {
+        assertSql("select * from (select * from entity) e1 " +
+                "left join entity2 e2 on e1.id = e2.id",
+            "SELECT * FROM (SELECT * FROM entity WHERE entity.tenant_id = 1) e1 " +
+                "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1");
+
+        assertSql("select * from entity1 e1 " +
+                "left join (select * from entity2) e2 " +
+                "on e1.id = e2.id",
+            "SELECT * FROM entity1 e1 " +
+                "LEFT JOIN (SELECT * FROM entity2 WHERE entity2.tenant_id = 1) e2 " +
+                "ON e1.id = e2.id " +
+                "WHERE e1.tenant_id = 1");
+    }
+
+    @Test
+    void selectSubJoin() {
+
+        assertSql("select * FROM " +
+                "(entity1 e1 right JOIN entity2 e2 ON e1.id = e2.id)",
+            "SELECT * FROM " +
+                "(entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
+                "WHERE e2.tenant_id = 1");
+
+        assertSql("select * FROM " +
+                "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id)",
+            "SELECT * FROM " +
+                "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+                "WHERE e1.tenant_id = 1");
+
+
+        assertSql("select * FROM " +
+                "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id) " +
+                "right join entity3 e3 on e1.id = e3.id",
+            "SELECT * FROM " +
+                "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+                "RIGHT JOIN entity3 e3 ON e1.id = e3.id AND e1.tenant_id = 1 " +
+                "WHERE e3.tenant_id = 1");
+
+
+        assertSql("select * FROM entity e " +
+                "LEFT JOIN (entity1 e1 right join entity2 e2 ON e1.id = e2.id) " +
+                "on e.id = e2.id",
+            "SELECT * FROM entity e " +
+                "LEFT JOIN (entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
+                "ON e.id = e2.id AND e2.tenant_id = 1 " +
+                "WHERE e.tenant_id = 1");
+
+        assertSql("select * FROM entity e " +
+                "LEFT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
+                "on e.id = e2.id",
+            "SELECT * FROM entity e " +
+                "LEFT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+                "ON e.id = e2.id AND e1.tenant_id = 1 " +
+                "WHERE e.tenant_id = 1");
+
+        assertSql("select * FROM entity e " +
+                "RIGHT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
+                "on e.id = e2.id",
+            "SELECT * FROM entity e " +
+                "RIGHT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
+                "ON e.id = e2.id AND e.tenant_id = 1 " +
+                "WHERE e1.tenant_id = 1");
+    }
+
+
     @Test
     void selectLeftJoinMultipleTrailingOn() {
         // 多个 on 尾缀的
@@ -230,29 +346,55 @@ class TenantLineInnerInterceptorTest {
                 "inner join entity1 e1 on e1.id = e.id " +
                 "WHERE e.id = ? OR e.name = ?",
             "SELECT * FROM entity e " +
-                "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+                "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
+                "WHERE e.id = ? OR e.name = ?");
 
         assertSql("SELECT * FROM entity e " +
                 "inner join entity1 e1 on e1.id = e.id " +
                 "WHERE (e.id = ? OR e.name = ?)",
             "SELECT * FROM entity e " +
-                "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
+                "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
+                "WHERE (e.id = ? OR e.name = ?)");
+
+        // 隐式内连接
+        assertSql("SELECT * FROM entity,entity1 " +
+                "WHERE entity.id = entity1.id",
+            "SELECT * FROM entity, entity1 " +
+                "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
+
+        // SubJoin with 隐式内连接
+        assertSql("SELECT * FROM (entity,entity1) " +
+                "WHERE entity.id = entity1.id",
+            "SELECT * FROM (entity, entity1) " +
+                "WHERE entity.id = entity1.id " +
+                "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
+
+        assertSql("SELECT * FROM ((entity,entity1),entity2) " +
+                "WHERE entity.id = entity1.id and entity.id = entity2.id",
+            "SELECT * FROM ((entity, entity1), entity2) " +
+                "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
+                "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
+
+        assertSql("SELECT * FROM (entity,(entity1,entity2)) " +
+                "WHERE entity.id = entity1.id and entity.id = entity2.id",
+            "SELECT * FROM (entity, (entity1, entity2)) " +
+                "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
+                "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
+
+        // 沙雕的括号写法
+        assertSql("SELECT * FROM (((entity,entity1))) " +
+                "WHERE entity.id = entity1.id",
+            "SELECT * FROM (((entity, entity1))) " +
+                "WHERE entity.id = entity1.id " +
+                "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
 
-        // 垃圾 inner join todo
-//        assertSql("SELECT * FROM entity,entity1 " +
-//                "WHERE entity.id = entity1.id",
-//            "SELECT * FROM entity e " +
-//                "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-//                "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
     }
 
 
     @Test
     void selectWithAs() {
         assertSql("with with_as_A as (select * from entity) select * from with_as_A",
-            "WITH with_as_A AS (SELECT * FROM entity WHERE tenant_id = 1) SELECT * FROM with_as_A");
+            "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A");
     }
 
     void assertSql(String sql, String targetSql) {

+ 5 - 9
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/toolkit/SimpleQueryTest.java

@@ -29,7 +29,7 @@ public class SimpleQueryTest extends BaseDbTest<EntityMapper> {
         // 可叠加后续操作
         List<String> names = SimpleQuery.list(Wrappers.lambdaQuery(), Entity::getName, e -> Optional.ofNullable(e.getName()).map(String::toUpperCase).ifPresent(e::setName));
 
-        Assert.isTrue(names.equals(Arrays.asList("RUBEN", "A CHAO")), "Ops!");
+        Assert.isTrue(names.equals(Arrays.asList("RUBEN", null)), "Ops!");
     }
 
     @Test
@@ -47,12 +47,8 @@ public class SimpleQueryTest extends BaseDbTest<EntityMapper> {
         // 校验结果
         Map<Long, String> map = new HashMap<>(1 << 2);
         map.put(1L, "ruben");
-        map.put(2L, "a chao");
+        map.put(2L, null);
         Assert.isTrue(idNameMap.equals(map), "Ops!");
-
-        // 同样支持叠加后续操作
-//        SimpleQuery.keyMap(Wrappers.lambdaQuery(), Entity::getId, System.out::println, System.out::println);
-
     }
 
     @Test
@@ -71,8 +67,8 @@ public class SimpleQueryTest extends BaseDbTest<EntityMapper> {
         Map<String, List<Entity>> map = new HashMap<>(1 << 2);
         Entity chao = new Entity();
         chao.setId(2L);
-        chao.setName("a chao");
-        map.put("a chao", Collections.singletonList(chao));
+        chao.setName(null);
+        map.put(null, Collections.singletonList(chao));
 
         Entity ruben = new Entity();
         ruben.setId(1L);
@@ -87,7 +83,7 @@ public class SimpleQueryTest extends BaseDbTest<EntityMapper> {
 
     @Override
     protected String tableDataSql() {
-        return "insert into entity(id,name) values(1,'ruben'),(2,'a chao');";
+        return "insert into entity(id,name) values(1,'ruben'),(2,null);";
     }
 
     @Override

+ 1 - 1
settings.gradle

@@ -9,7 +9,7 @@ buildscript {
     dependencies {
         //noinspection DifferentKotlinGradleVersion
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72"
-        classpath "gradle.plugin.com.hierynomus.gradle.plugins:license-gradle-plugin:0.15.0"
+        classpath "gradle.plugin.com.hierynomus.gradle.plugins:license-gradle-plugin:0.16.1"
         classpath "io.freefair.gradle:lombok-plugin:5.3.0"
     }
 }