Browse Source

处理 lambda 取值,优化 lambdawrapper 的 new 权限

miemie 7 years ago
parent
commit
3842e4eef7

+ 45 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractLambdaWrapper.java

@@ -0,0 +1,45 @@
+package com.baomidou.mybatisplus.core.conditions;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
+import com.baomidou.mybatisplus.core.toolkit.MapUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.Property;
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
+
+import java.util.Map;
+
+/**
+ * <p>
+ * Lambda 语法使用 Wrapper
+ * 统一处理解析 lambda 获取 column
+ * </p>
+ *
+ * @author hubin miemie HCL
+ * @since 2017-05-26
+ */
+public abstract class AbstractLambdaWrapper<T, This extends AbstractLambdaWrapper<T, This>> extends AbstractWrapper<T, Property<T, ?>, This> {
+    private Map<String, String> columnMap = null;
+    private boolean initColumnMap = false;
+
+    @Override
+    public String columnToString(Property<T, ?> column) {
+        return getColumn(LambdaUtils.resolve(column));
+    }
+
+    private String getColumn(SerializedLambda lambda) {
+        if (!initColumnMap) {
+            String entityClassName = lambda.getImplClass().replace("/", ".");
+            columnMap = LambdaUtils.getColumnMap(entityClassName);
+            if (MapUtils.isEmpty(columnMap)) {
+                throw new MybatisPlusException("该模式不能应用于非 baseMapper 的泛型 entity 之外的 entity");
+            }
+            initColumnMap = true;
+        }
+        String column = columnMap.get(StringUtils.resolveFieldName(lambda.getImplMethodName()));
+        if (column == null) {
+            throw new MybatisPlusException("该模式不能应用于非数据库字段");
+        }
+        return column;
+    }
+}

+ 6 - 27
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/update/LambdaUpdateWrapper.java

@@ -1,38 +1,21 @@
 package com.baomidou.mybatisplus.core.conditions.update;
 
+import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
+
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
-import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
-
 /**
  * @author hubin miemie HCL
  * @since 2018-05-30
  */
-public class LambdaUpdateWrapper<T> extends AbstractWrapper<T, Property<T, ?>, LambdaUpdateWrapper<T>> {
-
+public class LambdaUpdateWrapper<T> extends AbstractLambdaWrapper<T, LambdaUpdateWrapper<T>> {
     /**
      * SQL 更新字段内容,例如:name='1',age=2
      */
     protected String sqlSet;
 
-    public LambdaUpdateWrapper() {
-        this(null, null);
-    }
-
-    public LambdaUpdateWrapper(T entity) {
-        this(entity, null);
-    }
-
-    public LambdaUpdateWrapper(T entity, String sqlSet) {
-        this.entity = entity;
-        this.sqlSet = sqlSet;
-        this.initNeed();
-    }
-
-    private LambdaUpdateWrapper(T entity, String sqlSet, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs) {
+    LambdaUpdateWrapper(T entity, String sqlSet, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs) {
         this.entity = entity;
         this.sqlSet = sqlSet;
         this.paramNameSeq = paramNameSeq;
@@ -44,13 +27,9 @@ public class LambdaUpdateWrapper<T> extends AbstractWrapper<T, Property<T, ?>, L
         return sqlSet;
     }
 
-    public void setSqlSet(String sqlSet) {
+    public LambdaUpdateWrapper<T> setSqlSet(String sqlSet) {
         this.sqlSet = sqlSet;
-    }
-
-    @Override
-    public String columnToString(Property<T, ?> column) {
-        return TableInfoHelper.toColumn(column);
+        return typedThis();
     }
 
     @Override

+ 3 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/update/UpdateWrapper.java

@@ -1,10 +1,10 @@
 package com.baomidou.mybatisplus.core.conditions.update;
 
+import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
+
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
-
 /**
  * <p>
  * Update 条件封装
@@ -42,7 +42,7 @@ public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T
     }
 
     public LambdaUpdateWrapper<T> stream() {
-        return new LambdaUpdateWrapper<>(this.entity, this.sqlSet);
+        return new LambdaUpdateWrapper<>(entity, sqlSet, paramNameSeq, paramNameValuePairs);
     }
 
     @Override

+ 16 - 16
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/where/EntityWrapper.java

@@ -16,13 +16,13 @@
 package com.baomidou.mybatisplus.core.conditions.where;
 
 
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
 import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
 
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * <p>
  * Entity 对象封装操作类
@@ -39,18 +39,6 @@ public class EntityWrapper<T> extends AbstractWrapper<T, String, EntityWrapper<T
     private String sqlSelect;
 
 
-    @Override
-    public String getSqlSelect() {
-        return StringUtils.isEmpty(sqlSelect) ? null : SqlUtils.stripSqlInjection(sqlSelect);
-    }
-
-    public EntityWrapper<T> setSqlSelect(String sqlSelect) {
-        if (StringUtils.isNotEmpty(sqlSelect)) {
-            this.sqlSelect = sqlSelect;
-        }
-        return this;
-    }
-
     public EntityWrapper() {
         this(null, null);
     }
@@ -72,8 +60,20 @@ public class EntityWrapper<T> extends AbstractWrapper<T, String, EntityWrapper<T
         this.paramNameValuePairs = paramNameValuePairs;
     }
 
+    @Override
+    public String getSqlSelect() {
+        return StringUtils.isEmpty(sqlSelect) ? null : SqlUtils.stripSqlInjection(sqlSelect);
+    }
+
+    public EntityWrapper<T> setSqlSelect(String sqlSelect) {
+        if (StringUtils.isNotEmpty(sqlSelect)) {
+            this.sqlSelect = sqlSelect;
+        }
+        return typedThis();
+    }
+
     public LambdaEntityWrapper<T> stream() {
-        return new LambdaEntityWrapper<>(this.entity, this.sqlSelect);
+        return new LambdaEntityWrapper<>(entity, sqlSelect, paramNameSeq, paramNameValuePairs);
     }
 
     @Override

+ 7 - 28
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/where/LambdaEntityWrapper.java

@@ -15,14 +15,12 @@
  */
 package com.baomidou.mybatisplus.core.conditions.where;
 
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
+import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
 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.Property;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * <p>
@@ -32,29 +30,14 @@ import com.baomidou.mybatisplus.core.toolkit.support.Property;
  * @author hubin miemie HCL
  * @since 2017-05-26
  */
-public class LambdaEntityWrapper<T> extends AbstractWrapper<T, Property<T, ?>, LambdaEntityWrapper<T>> {
+public class LambdaEntityWrapper<T> extends AbstractLambdaWrapper<T, LambdaEntityWrapper<T>> {
 
     /**
      * SQL 查询字段内容,例如:id,name,age
      */
     private String sqlSelect;
 
-
-    public LambdaEntityWrapper() {
-        this(null, null);
-    }
-
-    public LambdaEntityWrapper(T entity) {
-        this(entity, null);
-    }
-
-    public LambdaEntityWrapper(T entity, String sqlSelect) {
-        this.entity = entity;
-        this.sqlSelect = sqlSelect;
-        this.initNeed();
-    }
-
-    private LambdaEntityWrapper(T entity, String sqlSelect, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs) {
+    LambdaEntityWrapper(T entity, String sqlSelect, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs) {
         this.entity = entity;
         this.sqlSelect = sqlSelect;
         this.paramNameSeq = paramNameSeq;
@@ -70,13 +53,9 @@ public class LambdaEntityWrapper<T> extends AbstractWrapper<T, Property<T, ?>, L
         if (StringUtils.isNotEmpty(sqlSelect)) {
             this.sqlSelect = sqlSelect;
         }
-        return this;
+        return typedThis();
     }
 
-    @Override
-    public String columnToString(Property<T, ?> column) {
-        return TableInfoHelper.toColumn(column);
-    }
 
     @Override
     protected LambdaEntityWrapper<T> instance(AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs) {

+ 4 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtils.java

@@ -53,4 +53,8 @@ public final class LambdaUtils {
         tableInfo.getFieldList().forEach(i -> map.put(i.getProperty(), i.getColumn()));
         return map;
     }
+
+    public static Map<String, String> getColumnMap(String entityClassName) {
+        return LAMBDA_CACHE.get(entityClassName);
+    }
 }

+ 20 - 5
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringUtils.java

@@ -60,13 +60,10 @@ public class StringUtils {
      * 占位符
      */
     public static final String PLACE_HOLDER = "{%s}";
-
-    private static boolean separatorBeforeDigit = false;
-    private static boolean separatorAfterDigit = true;
-
     private static final Pattern PATTERN_ONE = Pattern.compile(".*[A-Z]+.*");
-
     private static final Pattern PATTERN_TWO = Pattern.compile(".*[/_]+.*");
+    private static boolean separatorBeforeDigit = false;
+    private static boolean separatorAfterDigit = true;
 
 
     private StringUtils() {
@@ -150,6 +147,24 @@ public class StringUtils {
         return sb.toString();
     }
 
+    /**
+     * <p>
+     * 解析 getMethodName -> propertyName
+     * </p>
+     *
+     * @param getMethodName 需要解析的
+     * @return 返回解析后的字段名称
+     */
+    public static String resolveFieldName(String getMethodName) {
+        if (getMethodName.startsWith("get")) {
+            getMethodName = getMethodName.substring(3, getMethodName.length());
+        } else if (getMethodName.startsWith("is")) {
+            getMethodName = getMethodName.substring(2, getMethodName.length());
+        }
+        // 小写第一个字母
+        return StringUtils.firstToLowerCase(getMethodName);
+    }
+
     /**
      * <p>
      * 字符串下划线转驼峰格式

+ 4 - 68
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/TableInfoHelper.java

@@ -23,8 +23,6 @@ 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.sql.SqlHelper;
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
-import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
 import org.apache.ibatis.builder.MapperBuilderAssistant;
 import org.apache.ibatis.executor.keygen.KeyGenerator;
 import org.apache.ibatis.executor.keygen.NoKeyGenerator;
@@ -40,7 +38,10 @@ import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.SqlSessionFactory;
 
 import java.lang.reflect.Field;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -68,71 +69,6 @@ public class TableInfoHelper {
      */
     private static final String DEFAULT_ID_NAME = "id";
 
-    /**
-     * @param func 需要进行转换的 func
-     * @param <T>  被函数调用的类型,这个必须指定
-     * @return 返回解析后的列名
-     */
-    public static <T> String toColumn(Property<T, ?> func) {//todo 只需要返回className以及methodName,放到lamWrapper里根据缓存取出columnName
-        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 filedName;
-        // 为防止后面字段,驼峰等信息根据配置发生变化,此处不自己解析字段信息
-//        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
-     */
-    @Deprecated
-    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>
      * 获取实体映射表信息

+ 3 - 3
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/test/WrapperTest.java

@@ -1,9 +1,8 @@
 package com.baomidou.mybatisplus.core.test;
 
-import org.junit.Test;
-
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.where.EntityWrapper;
+import org.junit.Test;
 
 public class WrapperTest {
 
@@ -13,10 +12,11 @@ public class WrapperTest {
 
     @Test
     public void test() {
-        Wrapper wrapper = new EntityWrapper<User>().stream().eq(User::getName, 123)
+        Wrapper<User> wrapper = new EntityWrapper<User>().stream().eq(User::getName, 123)
             .or(c -> c.eq(User::getRoleId, 1).eq(User::getId, 2))
             .and().eq(User::getId, 1);
         log(wrapper.getSqlSegment());
+
     }
 
     @Test

+ 3 - 5
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtilsTest.java

@@ -1,12 +1,10 @@
 package com.baomidou.mybatisplus.core.toolkit;
 
-import org.junit.Assert;
-import org.junit.Test;
-
 import com.baomidou.mybatisplus.core.toolkit.support.Property;
 import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
-
 import lombok.Getter;
+import org.junit.Assert;
+import org.junit.Test;
 
 public class LambdaUtilsTest {
 
@@ -15,7 +13,7 @@ public class LambdaUtilsTest {
         SerializedLambda lambda = LambdaUtils.resolve(TestPojo::getId);
         Assert.assertEquals(TestPojo.class.getName(), lambda.getImplClass().replace("/", "."));
         Assert.assertEquals("getId", lambda.getImplMethodName());
-        Assert.assertEquals("id", TableInfoHelper.toColumn(TestPojo::getId));
+        Assert.assertEquals("id", StringUtils.resolveFieldName(lambda.getImplMethodName()));
 
         Cond<TestPojo> cond = new Cond<>();
         System.out.println(cond.eq(TestPojo::getId, 123).toString());