Browse Source

Wrapper包装SQL添加处理多重嵌套的情况

Caratacus 7 years ago
parent
commit
4ebd831abf

+ 25 - 8
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/EntityWrapperTest.java

@@ -159,12 +159,12 @@ public class EntityWrapperTest {
 		 */
 		 */
         ew.setEntity(new User(1));
         ew.setEntity(new User(1));
         ew.where("name=?", "'zhangsan'").and("id=1").orNew("status=?", "0").or("status=1").notLike("nlike", "notvalue")
         ew.where("name=?", "'zhangsan'").and("id=1").orNew("status=?", "0").or("status=1").notLike("nlike", "notvalue")
-                .andNew("new=xx").like("hhh", "ddd").andNew("pwd=11").isNotNull("n1,n2").isNull("n3").groupBy("x1")
-                .groupBy("x2,x3").having("x1=11").having("x3=433").orderBy("dd").orderBy("d1,d2");
+            .andNew("new=xx").like("hhh", "ddd").andNew("pwd=11").isNotNull("n1,n2").isNull("n3").groupBy("x1")
+            .groupBy("x2,x3").having("x1=11").having("x3=433").orderBy("dd").orderBy("d1,d2");
         System.out.println(ew.originalSql());
         System.out.println(ew.originalSql());
         Assert.assertEquals("AND (name=? AND id=1) \n" + "OR (status=? OR status=1 AND nlike NOT LIKE ?) \n"
         Assert.assertEquals("AND (name=? AND id=1) \n" + "OR (status=? OR status=1 AND nlike NOT LIKE ?) \n"
-                + "AND (new=xx AND hhh LIKE ?) \n" + "AND (pwd=11 AND n1 IS NOT NULL AND n2 IS NOT NULL AND n3 IS NULL)\n"
-                + "GROUP BY x1, x2,x3\n" + "HAVING (x1=11 AND x3=433)\n" + "ORDER BY dd, d1,d2", ew.originalSql());
+            + "AND (new=xx AND hhh LIKE ?) \n" + "AND (pwd=11 AND n1 IS NOT NULL AND n2 IS NOT NULL AND n3 IS NULL)\n"
+            + "GROUP BY x1, x2,x3\n" + "HAVING (x1=11 AND x3=433)\n" + "ORDER BY dd, d1,d2", ew.originalSql());
     }
     }
 
 
     @Test
     @Test
@@ -310,8 +310,8 @@ public class EntityWrapperTest {
         String sqlPart = Condition.create().gt("gt", 1).le("le", 2).lt("le", 3).ge("ge", 4).eq("eq", 5).allEq(map).originalSql();
         String sqlPart = Condition.create().gt("gt", 1).le("le", 2).lt("le", 3).ge("ge", 4).eq("eq", 5).allEq(map).originalSql();
         System.out.println("sql ==> " + sqlPart);
         System.out.println("sql ==> " + sqlPart);
         Assert.assertEquals(
         Assert.assertEquals(
-                "AND (gt > ? AND le <= ? AND le < ? AND ge >= ? AND eq = ? AND allEq1 = ? AND allEq2 = ? AND allEq3 = ?)",
-                sqlPart);
+            "AND (gt > ? AND le <= ? AND le < ? AND ge >= ? AND eq = ? AND allEq1 = ? AND allEq2 = ? AND allEq3 = ?)",
+            sqlPart);
     }
     }
 
 
     /**
     /**
@@ -320,7 +320,7 @@ public class EntityWrapperTest {
     @Test
     @Test
     public void testlike() {
     public void testlike() {
         String sqlPart = Condition.create().like("default", "default", SqlLike.DEFAULT).like("left", "left", SqlLike.LEFT)
         String sqlPart = Condition.create().like("default", "default", SqlLike.DEFAULT).like("left", "left", SqlLike.LEFT)
-                .like("right", "right", SqlLike.RIGHT).originalSql();
+            .like("right", "right", SqlLike.RIGHT).originalSql();
         System.out.println("sql ==> " + sqlPart);
         System.out.println("sql ==> " + sqlPart);
         Assert.assertEquals("AND (default LIKE ? AND left LIKE ? AND right LIKE ?)", sqlPart);
         Assert.assertEquals("AND (default LIKE ? AND left LIKE ? AND right LIKE ?)", sqlPart);
     }
     }
@@ -338,7 +338,7 @@ public class EntityWrapperTest {
         ew.or("sql = {0}", "sql").like("default", "default", SqlLike.DEFAULT).like("left", "left", SqlLike.LEFT);
         ew.or("sql = {0}", "sql").like("default", "default", SqlLike.DEFAULT).like("left", "left", SqlLike.LEFT);
         ew.in("aaabbbcc", "1,3,4");
         ew.in("aaabbbcc", "1,3,4");
         String sqlPart = ew.in("bbb", Arrays.asList(new String[]{"a", "b", "c"})).like("right", "right", SqlLike.RIGHT).isWhere(true)
         String sqlPart = ew.in("bbb", Arrays.asList(new String[]{"a", "b", "c"})).like("right", "right", SqlLike.RIGHT).isWhere(true)
-                .eq("bool", true).between("ee", "1111", "222").originalSql();
+            .eq("bool", true).between("ee", "1111", "222").originalSql();
         System.out.println("sql ==> " + sqlPart);
         System.out.println("sql ==> " + sqlPart);
         Assert.assertEquals("WHERE (sql = ? AND default LIKE ? AND left LIKE ? AND aaabbbcc IN (?,?,?) AND bbb IN (?,?,?) AND right LIKE ? AND bool = ? AND ee BETWEEN ? AND ?)", sqlPart);
         Assert.assertEquals("WHERE (sql = ? AND default LIKE ? AND left LIKE ? AND aaabbbcc IN (?,?,?) AND bbb IN (?,?,?) AND right LIKE ? AND bool = ? AND ee BETWEEN ? AND ?)", sqlPart);
         System.out.println(ew.getSqlSegment());
         System.out.println(ew.getSqlSegment());
@@ -435,4 +435,21 @@ public class EntityWrapperTest {
         Assert.assertEquals("ORDER BY id1 ASC, id2 ASC, id3 ASC, id1 DESC, id2 DESC, id3 DESC", wrapper.getSqlSegment());
         Assert.assertEquals("ORDER BY id1 ASC, id2 ASC, id3 ASC, id1 DESC, id2 DESC, id3 DESC", wrapper.getSqlSegment());
     }
     }
 
 
+    @Test
+    public void testNest1() {
+        String sqlSegment = Condition.create().eq("aaa", "aaa").andNew().leftNest().eq("a", "a").orNew().eq("b", "b").eq("c", "c").rightNest().originalSql();
+        Assert.assertEquals(sqlSegment, "AND (aaa = ?) \n" +
+            "AND ((a = ?) \n" +
+            "OR (b = ? AND c = ?))");
+    }
+
+    @Test
+    public void testNest2() {
+        String sqlSegment = Condition.create().eq("aaa", "aaa").andNew().leftNest(2).eq("a", "a").orNew().eq("b", "b").eq("c", "c").rightNest().orNew().eq("d", "d").eq("e", "e").rightNest().originalSql();
+        Assert.assertEquals(sqlSegment, "AND (aaa = ?) \n" +
+            "AND (((a = ?) \n" +
+            "OR (b = ? AND c = ?)) \n" +
+            "OR (d = ? AND e = ?))");
+    }
+
 }
 }

+ 32 - 1
mybatis-plus-support/src/main/java/com/baomidou/mybatisplus/MybatisAbstractSQL.java

@@ -19,6 +19,7 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
+import java.util.regex.Pattern;
 
 
 import com.baomidou.mybatisplus.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
@@ -38,6 +39,8 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
     private static final String OR = " OR ";
     private static final String OR = " OR ";
     private static final String AND_NEW = ") \nAND (";
     private static final String AND_NEW = ") \nAND (";
     private static final String OR_NEW = ") \nOR (";
     private static final String OR_NEW = ") \nOR (";
+    private static final Pattern pattern = Pattern.compile("[(|)|\\s]+");
+
 
 
     /**
     /**
      * SQL条件
      * SQL条件
@@ -72,6 +75,20 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
         return getSelf();
         return getSelf();
     }
     }
 
 
+    /**
+     * <p>
+     * 补充方法,一般认为填补mp一个条件中多重嵌套解决方案
+     * 注:参数请不要传入外界动态参数否则可能会产生sql注入的危险
+     * </p>
+     *
+     * @param supp 补充语句
+     * @return this
+     */
+    public T SUPP(String supp) {
+        sql().where.add(supp);
+        return getSelf();
+    }
+
     public T AND_NEW() {
     public T AND_NEW() {
         sql().lastList.add(AND_NEW);
         sql().lastList.add(AND_NEW);
         return getSelf();
         return getSelf();
@@ -199,7 +216,10 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
                             last = part;
                             last = part;
                             continue;
                             continue;
                         } else {
                         } else {
-                            builder.append(conjunction);
+                            //not nest append conjunction
+                            if (!checkNest(part) && !checkNest(last)) {
+                                builder.append(conjunction);
+                            }
                         }
                         }
                     }
                     }
                     builder.append(part);
                     builder.append(part);
@@ -246,5 +266,16 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
         public String sql(Appendable appendable) {
         public String sql(Appendable appendable) {
             return buildSQL(new SafeAppendable(appendable));
             return buildSQL(new SafeAppendable(appendable));
         }
         }
+
+        /**
+         * 检查是否嵌套
+         *
+         * @param args
+         * @return true 嵌套
+         */
+        private boolean checkNest(String args) {
+            return pattern.matcher(args).matches();
+        }
     }
     }
 }
 }
+

+ 70 - 1
mybatis-plus-support/src/main/java/com/baomidou/mybatisplus/mapper/Wrapper.java

@@ -580,7 +580,6 @@ public abstract class Wrapper<T> implements Serializable {
      * <p>
      * <p>
      * 使用AND连接并换行
      * 使用AND连接并换行
      * </p>
      * </p>
-     * <p>
      *
      *
      * @return this
      * @return this
      */
      */
@@ -589,6 +588,76 @@ public abstract class Wrapper<T> implements Serializable {
         return this;
         return this;
     }
     }
 
 
+    /**
+     * <p>
+     * 左嵌套方法
+     * </p>
+     *
+     * @return this
+     */
+    public Wrapper<T> leftNest() {
+        leftNest(1);
+        return this;
+    }
+
+    /**
+     * <p>
+     * 右嵌套方法
+     * </p>
+     *
+     * @return this
+     */
+    public Wrapper<T> rightNest() {
+        rightNest(1);
+        return this;
+    }
+
+    /**
+     * <p>
+     * 左嵌套方法,一般认为填补mp一个条件中多重嵌套解决方案
+     * </p>
+     *
+     * @param num 嵌套数量
+     * @return this
+     */
+    public Wrapper<T> leftNest(int num) {
+        nest("(", num);
+        return this;
+    }
+
+    /**
+     * <p>
+     * 右嵌套方法,一般认为填补mp一个条件中多重嵌套解决方案
+     * </p>
+     *
+     * @param num 嵌套数量
+     * @return this
+     */
+    public Wrapper<T> rightNest(int num) {
+        nest(")", num);
+        return this;
+    }
+
+    /**
+     * <p>
+     * 嵌套方法,一般认为填补mp一个条件中多重嵌套解决方案
+     * </p>
+     *
+     * @param nest 嵌套字符串 "(" or ")"
+     * @param num  嵌套数量
+     * @return this
+     */
+    private Wrapper<T> nest(String nest, int num) {
+        if (num >= 1) {
+            StringBuilder builder = new StringBuilder(num);
+            for (int i = 0; i < num; i++) {
+                builder.append(nest);
+            }
+            sql.SUPP(builder.toString());
+        }
+        return this;
+    }
+
     /**
     /**
      * <p>
      * <p>
      * 使用OR连接并换行
      * 使用OR连接并换行