Browse Source

基本完善 sql 优化

miemie 7 years ago
parent
commit
07a3a0e639

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

@@ -36,7 +36,6 @@ import static com.baomidou.mybatisplus.core.enums.SqlKeyword.NOT;
 import static com.baomidou.mybatisplus.core.enums.SqlKeyword.OR;
 import static com.baomidou.mybatisplus.core.enums.SqlKeyword.ORDER_BY;
 import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
 
 import java.io.Serializable;
 import java.util.Arrays;
@@ -55,7 +54,7 @@ import com.baomidou.mybatisplus.core.enums.SqlKeyword;
 import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.baomidou.mybatisplus.core.toolkit.sql.SqlSegmentList;
+import com.baomidou.mybatisplus.core.toolkit.sql.segments.JoinSegment;
 
 
 /**
@@ -66,6 +65,7 @@ import com.baomidou.mybatisplus.core.toolkit.sql.SqlSegmentList;
  * @author hubin miemie HCL
  * @since 2017-05-26
  */
+@SuppressWarnings("unchecked,serial")
 public abstract class AbstractWrapper<T, R, This extends AbstractWrapper<T, R, This>> extends Wrapper<T>
     implements Compare<This, R>, Nested<This>, Join<This>, Func<This, R>, Serializable {
 
@@ -90,7 +90,7 @@ public abstract class AbstractWrapper<T, R, This extends AbstractWrapper<T, R, T
      * 数据库表映射实体类
      */
     protected T entity;
-    private SqlSegmentList expression = new SqlSegmentList();
+    private JoinSegment expression = new JoinSegment();
 
     @Override
     public T getEntity() {
@@ -549,7 +549,7 @@ public abstract class AbstractWrapper<T, R, This extends AbstractWrapper<T, R, T
      */
     protected This doIt(boolean condition, ISqlSegment... sqlSegments) {
         if (condition) {
-            expression.addAll(Arrays.asList(sqlSegments));
+            expression.add(sqlSegments);
         }
         return typedThis;
     }
@@ -560,11 +560,7 @@ public abstract class AbstractWrapper<T, R, This extends AbstractWrapper<T, R, T
 
     @Override
     public String getSqlSegment() {
-        String temp = String.join(" ", expression.stream().map(ISqlSegment::getSqlSegment).collect(toList()));
-        if (temp.startsWith(ORDER_BY.getSqlSegment()) || temp.startsWith(AND.getSqlSegment())) {
-            return " 1=1 " + temp;
-        }
-        return temp;
+        return expression.getSqlSegment();
     }
 
     public Map<String, Object> getParamNameValuePairs() {

+ 9 - 4
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/segments/GroupBySegment.java

@@ -15,6 +15,9 @@
  */
 package com.baomidou.mybatisplus.core.toolkit.sql.segments;
 
+import static com.baomidou.mybatisplus.core.enums.SqlKeyword.GROUP_BY;
+import static java.util.stream.Collectors.joining;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -32,14 +35,16 @@ public class GroupBySegment extends ArrayList<ISqlSegment> implements ISqlSegmen
     @Override
     public boolean addAll(Collection<? extends ISqlSegment> c) {
         List<ISqlSegment> list = new ArrayList<>(c);
-        if (!isEmpty()) {
-            list.remove(0);
-        }
+        list.remove(0);
         return super.addAll(list);
     }
 
     @Override
     public String getSqlSegment() {
-        return null;
+        if (isEmpty()) {
+            return "";
+        }
+        return this.stream().map(ISqlSegment::getSqlSegment).collect(joining(",",
+            " " + GROUP_BY.getSqlSegment() + " ", ""));
     }
 }

+ 5 - 30
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/segments/JoinSegment.java

@@ -15,12 +15,13 @@
  */
 package com.baomidou.mybatisplus.core.toolkit.sql.segments;
 
+import static com.baomidou.mybatisplus.core.toolkit.sql.segments.MatchSegment.GROUP_BY;
+import static com.baomidou.mybatisplus.core.toolkit.sql.segments.MatchSegment.ORDER_BY;
+
 import java.util.Arrays;
 import java.util.List;
-import java.util.function.Predicate;
 
 import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
-import com.baomidou.mybatisplus.core.enums.SqlKeyword;
 
 /**
  * @author miemie
@@ -37,43 +38,17 @@ public class JoinSegment implements ISqlSegment {
     public void add(ISqlSegment... iSqlSegments) {
         List<ISqlSegment> list = Arrays.asList(iSqlSegments);
         ISqlSegment sqlSegment = list.get(0);
-        if (match(PredicateStrategy.ORDER_BY, sqlSegment)) {
+        if (MatchSegment.match(ORDER_BY, sqlSegment)) {
             orderBySegment.addAll(list);
-        } else if (match(PredicateStrategy.GROUP_BY, sqlSegment)) {
+        } else if (MatchSegment.match(GROUP_BY, sqlSegment)) {
             groupBySegment.addAll(list);
         } else {
             normalSegment.addAll(list);
         }
     }
 
-    private boolean match(PredicateStrategy predicateStrategy, ISqlSegment value) {
-        return predicateStrategy.getPredicate().test(value);
-    }
-
     @Override
     public String getSqlSegment() {
         return normalSegment.getSqlSegment() + groupBySegment.getSqlSegment() + orderBySegment.getSqlSegment();
     }
-
-    /**
-     * 验证策略
-     */
-    private enum PredicateStrategy {
-        GROUP_BY(i -> i == SqlKeyword.GROUP_BY),
-        ORDER_BY(i -> i == SqlKeyword.ORDER_BY),
-        NOT(i -> i == SqlKeyword.NOT),
-        AND(i -> i == SqlKeyword.AND),
-        OR(i -> i == SqlKeyword.OR),
-        AND_OR(i -> i == SqlKeyword.AND || i == SqlKeyword.OR);
-
-        private Predicate<ISqlSegment> predicate;
-
-        PredicateStrategy(Predicate<ISqlSegment> predicate) {
-            this.predicate = predicate;
-        }
-
-        public Predicate<ISqlSegment> getPredicate() {
-            return predicate;
-        }
-    }
 }

+ 33 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/segments/MatchSegment.java

@@ -0,0 +1,33 @@
+package com.baomidou.mybatisplus.core.toolkit.sql.segments;
+
+import java.util.function.Predicate;
+
+import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
+import com.baomidou.mybatisplus.core.enums.SqlKeyword;
+
+/**
+ * @author miemie
+ * @since 2018-06-27
+ */
+enum MatchSegment {
+    GROUP_BY(i -> i == SqlKeyword.GROUP_BY),
+    ORDER_BY(i -> i == SqlKeyword.ORDER_BY),
+    NOT(i -> i == SqlKeyword.NOT),
+    AND(i -> i == SqlKeyword.AND),
+    OR(i -> i == SqlKeyword.OR),
+    AND_OR(i -> i == SqlKeyword.AND || i == SqlKeyword.OR);
+
+    private final Predicate<ISqlSegment> predicate;
+
+    MatchSegment(Predicate<ISqlSegment> predicate) {
+        this.predicate = predicate;
+    }
+
+    protected static boolean match(MatchSegment matchSegment, ISqlSegment segment) {
+        return matchSegment.getPredicate().test(segment);
+    }
+
+    protected Predicate<ISqlSegment> getPredicate() {
+        return predicate;
+    }
+}

+ 57 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/segments/NormalSegment.java

@@ -15,10 +15,18 @@
  */
 package com.baomidou.mybatisplus.core.toolkit.sql.segments;
 
+import static com.baomidou.mybatisplus.core.toolkit.sql.segments.MatchSegment.AND;
+import static com.baomidou.mybatisplus.core.toolkit.sql.segments.MatchSegment.AND_OR;
+import static com.baomidou.mybatisplus.core.toolkit.sql.segments.MatchSegment.NOT;
+import static com.baomidou.mybatisplus.core.toolkit.sql.segments.MatchSegment.OR;
+
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import java.util.stream.Collectors;
 
 import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
+import com.baomidou.mybatisplus.core.enums.SqlKeyword;
 
 /**
  * @author miemie
@@ -27,9 +35,57 @@ import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
 public class NormalSegment extends ArrayList<ISqlSegment> implements ISqlSegment {
 
     private static final long serialVersionUID = -1991374407733611565L;
+    /**
+     * 最后一个值
+     */
+    private ISqlSegment lastValue = null;
+
+    @Override
+    public boolean addAll(Collection<? extends ISqlSegment> c) {
+        List<ISqlSegment> list = new ArrayList<>(c);
+        ISqlSegment sqlSegment = list.get(0);
+        if (list.size() == 1) {
+            /**
+             * 只有 and() 以及 or() 以及 not() 会进入
+             */
+            if (!MatchSegment.match(NOT, sqlSegment)) {
+                //不是 not
+                if (isEmpty()) {
+                    //sqlSegment是 and 或者 or 并且在第一位,不继续执行
+                    return false;
+                }
+                boolean matchLastAnd = MatchSegment.match(AND, lastValue);
+                boolean matchLastOr = MatchSegment.match(OR, lastValue);
+                if (matchLastAnd || matchLastOr) {
+                    //上次最后一个值是 and 或者 or
+                    if (matchLastAnd && MatchSegment.match(AND, sqlSegment)) {
+                        return false;
+                    } else if (matchLastOr && MatchSegment.match(OR, sqlSegment)) {
+                        return false;
+                    } else {
+                        //和上次的不一样
+                        removeLast();
+                    }
+                }
+            }
+        } else if (!MatchSegment.match(AND_OR, lastValue) && !isEmpty()) {
+            add(SqlKeyword.AND);
+        }
+        //后置处理
+        this.flushLastValue(list);
+        return super.addAll(list);
+    }
+
+    private void flushLastValue(List<? extends ISqlSegment> list) {
+        lastValue = list.get(list.size() - 1);
+    }
+
+    private void removeLast() {//todo
+        remove(size() - 1);
+    }
 
     @Override
     public String getSqlSegment() {
-        return this.stream().map(ISqlSegment::getSqlSegment).collect(Collectors.joining("and"));
+        return this.stream().map(ISqlSegment::getSqlSegment).collect(Collectors.joining(" "));
     }
 }

+ 20 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/sql/segments/OrderBySegment.java

@@ -15,8 +15,12 @@
  */
 package com.baomidou.mybatisplus.core.toolkit.sql.segments;
 
+import static com.baomidou.mybatisplus.core.enums.SqlKeyword.ORDER_BY;
+import static java.util.stream.Collectors.joining;
+
 import java.util.ArrayList;
-import java.util.stream.Collectors;
+import java.util.Collection;
+import java.util.List;
 
 import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
 
@@ -28,8 +32,22 @@ public class OrderBySegment extends ArrayList<ISqlSegment> implements ISqlSegmen
 
     private static final long serialVersionUID = -294655105160779712L;
 
+    @Override
+    public boolean addAll(Collection<? extends ISqlSegment> c) {
+        List<ISqlSegment> list = new ArrayList<>(c);
+        list.remove(0);
+        if (!isEmpty()) {
+            super.add(() -> ",");
+        }
+        return super.addAll(list);
+    }
+
     @Override
     public String getSqlSegment() {
-        return this.stream().map(ISqlSegment::getSqlSegment).collect(Collectors.joining(","));
+        if (isEmpty()) {
+            return "";
+        }
+        return this.stream().map(ISqlSegment::getSqlSegment).collect(joining(" ",
+            " " + ORDER_BY.getSqlSegment() + " ", ""));
     }
 }

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

@@ -94,8 +94,10 @@ public class WrapperTest {
         logSqlSegment("嵌套测试,套内外手动拼接 or,去除套内第一个 or", new QueryWrapper<User>()
             .eq("id", 11).or(i -> i.or().eq("id", 1)).or().eq("id", 1));
 
-        logSqlSegment("多个 order by 拼接,", new QueryWrapper<User>()
-            .eq("id", 11).orderByAsc("id", "name", "sex").orderByAsc("age", "txl"));
+        logSqlSegment("多个 order by 和 group by 拼接,自动优化顺序", new QueryWrapper<User>()
+            .eq("id", 11)
+            .orderByAsc("id", "name", "sex").orderByDesc("age", "txl")
+            .groupBy("id", "name", "sex").groupBy("id", "name"));
     }
 
 //    public void test() {