Browse Source

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

125473094@qq.com 7 years ago
parent
commit
7b559182fb

+ 3 - 8
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/MybatisAbstractSQL.java

@@ -20,6 +20,7 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
@@ -235,14 +236,8 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
          * @return
          */
         private List<String> clearNull(List<String> parts) {
-            List<String> temps = new ArrayList<>();
-            for (String part : parts) {
-                if (StringUtils.isEmpty(part)) {
-                    continue;
-                }
-                temps.add(part);
-            }
-            return temps;
+            return parts.stream().filter(part -> !StringUtils.isEmpty(part))
+                .collect(Collectors.toList());
         }
 
         /**

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

@@ -15,6 +15,8 @@
  */
 package com.baomidou.mybatisplus.core.conditions;
 
+import java.util.Arrays;
+
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 
 /**
@@ -117,12 +119,10 @@ public class SqlPlus extends MybatisAbstractSQL<SqlPlus> {
      */
     private void handlerNull(String columns, String sqlPart) {
         if (StringUtils.isNotEmpty(columns)) {
-            String[] cols = columns.split(",");
-            for (String col : cols) {
-                if (StringUtils.isNotEmpty(col.trim())) {
-                    WHERE(col + sqlPart);
-                }
-            }
+            Arrays.stream(columns.split(","))
+                .filter(col -> StringUtils.isNotEmpty(col.trim()))
+                .map(col -> col + sqlPart)
+                .forEach(this::WHERE);
         }
     }
 }

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

@@ -30,7 +30,9 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.MapUtils;
 import com.baomidou.mybatisplus.core.toolkit.SerializationUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedFunction;
 
 
 /**
@@ -38,7 +40,7 @@ import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
  * 条件构造抽象类,定义T-SQL语法
  * </p>
  *
- * @author hubin , yanghu , Dyang , Caratacus
+ * @author hubin , yanghu , Dyang , Caratacus, hcl
  * @Date 2016-11-7
  */
 public abstract class Wrapper<T> implements Serializable {
@@ -214,6 +216,31 @@ public abstract class Wrapper<T> implements Serializable {
         return eq(true, column, params);
     }
 
+    public Wrapper<T> eq(boolean condition, SerializedFunction<T, ?> func, Object params) {
+        if (condition) {
+            sql.WHERE(formatSql(String.format("%s = {0}", toCol(func)), params));
+        }
+        return this;
+    }
+
+    /**
+     * 为了支持字段重构做出的修改
+     * <p>
+     * 你可以在指定 Wrapper<T> 泛型的前提下这么使用:
+     * <p>
+     * Wrapper<User> wrapper = new EntityWrapper<User>();
+     * wrapper.eq(User::getUserName, "baomidou")
+     * <p>
+     * 改方法会根据规则(比如配置的字段映射、或者下划线规则)将 User::getUserName 转换为对应的数据库字段信息
+     *
+     * @param func   需要转换的 function
+     * @param params 参数信息
+     * @return 返回自身
+     */
+    public Wrapper<T> eq(SerializedFunction<T, ?> func, Object params) {
+        return eq(true, func, params);
+    }
+
     /**
      * <p>
      * 等同于SQL的"field <> value"表达式
@@ -1548,5 +1575,13 @@ public abstract class Wrapper<T> implements Serializable {
     public Wrapper<T> clone() {
         return SerializationUtils.clone(this);
     }
+
+    /**
+     * @param func function
+     * @return 返回从 function 中解析出的 column
+     */
+    protected String toCol(SerializedFunction<T, ?> func) {
+        return TableInfoHelper.toColumn(func);
+    }
 }
 

+ 71 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/TableInfoHelper.java

@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.baomidou.mybatisplus.core.toolkit.support.LambdaCache;
@@ -49,6 +50,8 @@ import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedFunction;
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
 
 /**
  * <p>
@@ -65,11 +68,79 @@ public class TableInfoHelper {
      * 缓存反射类表信息
      */
     private static final Map<String, TableInfo> TABLE_INFO_CACHE = new ConcurrentHashMap<>();
+
+    /**
+     * lambda 字段缓存
+     */
+    private static final Map<String, String> LAMBDA_COLUMN_CACHE = new ConcurrentHashMap<>();
     /**
      * 默认表主键
      */
     private static final String DEFAULT_ID_NAME = "id";
 
+    /**
+     * @param func 需要进行转换的 func
+     * @param <T>  被函数调用的类型,这个必须指定
+     * @return 返回解析后的列名
+     */
+    public static <T> String toColumn(SerializedFunction<T, ?> func) {
+        SerializedLambda lambda = LambdaUtils.resolve(func);
+        // 使用 class 名称和方法名称作为缓存的键值
+        String cacheKey = lambda.getImplClass() + lambda.getImplMethodName();
+        return Optional.ofNullable(LAMBDA_COLUMN_CACHE.get(cacheKey))
+            .orElseGet(() -> {
+                String column = resolveColumn(lambda);
+                LAMBDA_COLUMN_CACHE.put(cacheKey, column);
+                return column;
+            });
+    }
+
+    /**
+     * @param lambda 需要解析的 column
+     * @return 返回解析后列的信息
+     */
+    private static String resolveColumn(SerializedLambda lambda) {
+        String filedName = resolveFieldName(lambda);
+        // 为防止后面字段,驼峰等信息根据配置发生变化,此处不自己解析字段信息
+        return getTableInfo(resolveClass(lambda)).getFieldList().stream()
+            .filter(fieldInfo -> filedName.equals(fieldInfo.getProperty()))
+            .findAny()
+            .map(TableFieldInfo::getColumn)
+            .orElseThrow(() -> {
+                String message = String.format("没有根据 %s#%s 解析到对应的表列名称,您可能排除了该字段或者 %s 方法不是标准的 getter 方法"
+                    , lambda.getImplClass(), lambda.getImplMethodName(), lambda.getImplMethodName());
+                return new MybatisPlusException(message);
+            });
+    }
+
+    /**
+     * @param lambda 需要解析的 lambda
+     * @return 返回解析后的字段名称
+     */
+    private static String resolveFieldName(SerializedLambda lambda) {
+        String name = lambda.getImplMethodName();
+        if (name.startsWith("get")) {
+            name = name.substring(3, name.length());
+        } else if (name.startsWith("is")) {
+            name = name.substring(2, name.length());
+        }
+        // 小写第一个字母
+        return StringUtils.firstToLowerCase(name);
+    }
+
+    /**
+     * @param lambda 需要解析的 lambda
+     * @return 返回解析后的class
+     */
+    private static Class<?> resolveClass(SerializedLambda lambda) {
+        String className = lambda.getImplClass().replace('/', '.');
+        try {
+            return Class.forName(className);
+        } catch (ClassNotFoundException e) {    // 这个异常不可能发生
+            throw new MybatisPlusException("Class : " + className + " 不存在?你是怎么调用的?", e);
+        }
+    }
+
     /**
      * <p>
      * 获取实体映射表信息