Parcourir la source

Merge branch 'github3.0' into 3.0

hubin il y a 3 ans
Parent
commit
cc8d3a6e08

+ 27 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractWrapper.java

@@ -42,7 +42,7 @@ import static java.util.stream.Collectors.joining;
  * @author hubin miemie HCL
  * @since 2017-05-26
  */
-@SuppressWarnings({"serial", "unchecked"})
+@SuppressWarnings({"unchecked"})
 public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
     implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {
 
@@ -300,6 +300,30 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
             () -> String.format("(%s)", inValue)));
     }
 
+    @Override
+    public Children gtSql(boolean condition, R column, String inValue) {
+        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), GT,
+            () -> String.format("(%s)", inValue)));
+    }
+
+    @Override
+    public Children geSql(boolean condition, R column, String inValue) {
+        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), GE,
+            () -> String.format("(%s)", inValue)));
+    }
+
+    @Override
+    public Children ltSql(boolean condition, R column, String inValue) {
+        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), LT,
+            () -> String.format("(%s)", inValue)));
+    }
+
+    @Override
+    public Children leSql(boolean condition, R column, String inValue) {
+        return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), LE,
+            () -> String.format("(%s)", inValue)));
+    }
+
     @Override
     public Children notInSql(boolean condition, R column, String inValue) {
         return maybeDo(condition, () -> appendSqlSegments(columnToSqlSegment(column), NOT_IN,
@@ -441,6 +465,7 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
      * @param params  参数
      * @return sql片段
      */
+    @SuppressWarnings("SameParameterValue")
     protected final String formatSqlMaybeWithParam(String sqlStr, String mapping, Object... params) {
         if (StringUtils.isBlank(sqlStr)) {
             // todo 何时会这样?
@@ -581,6 +606,7 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
      * @param paramAlias 参数别名
      * @return Children
      */
+    @SuppressWarnings("unused")
     public Children setParamAlias(String paramAlias) {
         Assert.notEmpty(paramAlias, "paramAlias can not be empty!");
         Assert.isEmpty(paramNameValuePairs, "Please call this method before working!");
@@ -616,7 +642,6 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
      *
      * @param columns 多字段
      */
-    @Deprecated
     protected String columnsToString(List<R> columns) {
         return columns.stream().map(this::columnToString).collect(joining(StringPool.COMMA));
     }

+ 76 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/interfaces/Func.java

@@ -161,6 +161,82 @@ public interface Func<Children, R> extends Serializable {
      */
     Children inSql(boolean condition, R column, String inValue);
 
+    /**
+     * 字段 &gt; ( sql语句 )
+     * <p>例1: gtSql("id", "1, 2, 3, 4, 5, 6")</p>
+     * <p>例1: gtSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param condition
+     * @param column
+     * @param inValue
+     * @return
+     */
+    Children gtSql(boolean condition, R column, String inValue);
+
+    /**
+     * ignore
+     */
+    default Children gtSql(R column, String inValue) {
+        return gtSql(true, column, inValue);
+    }
+
+    /**
+     * 字段 >= ( sql语句 )
+     * <p>例1: geSql("id", "1, 2, 3, 4, 5, 6")</p>
+     * <p>例1: geSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param condition
+     * @param column
+     * @param inValue
+     * @return
+     */
+    Children geSql(boolean condition, R column, String inValue);
+
+    /**
+     * ignore
+     */
+    default Children geSql(R column, String inValue) {
+        return geSql(true, column, inValue);
+    }
+
+    /**
+     * 字段 &lt; ( sql语句 )
+     * <p>例1: ltSql("id", "1, 2, 3, 4, 5, 6")</p>
+     * <p>例1: ltSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param condition
+     * @param column
+     * @param inValue
+     * @return
+     */
+    Children ltSql(boolean condition, R column, String inValue);
+
+    /**
+     * ignore
+     */
+    default Children ltSql(R column, String inValue) {
+        return ltSql(true, column, inValue);
+    }
+
+    /**
+     * 字段 <= ( sql语句 )
+     * <p>例1: leSql("id", "1, 2, 3, 4, 5, 6")</p>
+     * <p>例1: leSql("id", "select id from table where name = 'JunJun'")</p>
+     *
+     * @param condition
+     * @param column
+     * @param inValue
+     * @return
+     */
+    Children leSql(boolean condition, R column, String inValue);
+
+    /**
+     * ignore
+     */
+    default Children leSql(R column, String inValue) {
+        return leSql(true, column, inValue);
+    }
+
     /**
      * ignore
      */
@@ -181,7 +257,6 @@ public interface Func<Children, R> extends Serializable {
      */
     Children notInSql(boolean condition, R column, String inValue);
 
-
     /**
      * 分组:GROUP BY 字段, ...
      * <p>例: groupBy("id")</p>
@@ -196,7 +271,6 @@ public interface Func<Children, R> extends Serializable {
         return groupBy(true, column);
     }
 
-
     /**
      * 分组:GROUP BY 字段, ...
      * <p>例: groupBy(Arrays.asList("id", "name"))</p>
@@ -269,7 +343,6 @@ public interface Func<Children, R> extends Serializable {
         return orderBy(condition, true, column, columns);
     }
 
-
     /**
      * 排序:ORDER BY 字段, ... DESC
      * <p>例: orderByDesc(true, "id")</p>

+ 9 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringUtils.java

@@ -102,6 +102,14 @@ public final class StringUtils {
         return !isBlank(cs);
     }
 
+    public static boolean isEmpty(CharSequence cs) {
+        return cs == null || cs.length() == 0;
+    }
+
+    public static boolean isNotEmpty(CharSequence cs) {
+        return !isEmpty(cs);
+    }
+
     /**
      * 判断字符串是不是驼峰命名
      *
@@ -328,7 +336,7 @@ public final class StringUtils {
      */
     public static boolean checkValNotNull(Object object) {
         if (object instanceof CharSequence) {
-            return isNotBlank((CharSequence) object);
+            return isNotEmpty((CharSequence) object);
         }
         return object != null;
     }

+ 3 - 1
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/conditions/QueryWrapperTest.java

@@ -106,9 +106,11 @@ class QueryWrapperTest extends BaseWrapperTest {
             .in("inColl", getList()).or().notIn("notInColl", getList())
             .in("inArray").notIn("notInArray", 5, 6, 7)
             .inSql("inSql", "1,2,3,4,5").notInSql("inSql", "1,2,3,4,5")
+            .gtSql("gtSql", "1,2,3,4,5").ltSql("ltSql", "1,2,3,4,5")
+            .geSql("geSql", "1,2,3,4,5").leSql("leSql", "1,2,3,4,5")
             .having("sum(age) > {0}", 1).having("id is not null")
             .func(entity.getId() != null, j -> j.eq("id", entity.getId()));// 不会npe,也不会加入sql
-        logSqlWhere("测试 Func 下的方法", queryWrapper, "(nullColumn IS NULL OR notNullColumn IS NOT NULL AND inColl IN (?,?) OR notInColl NOT IN (?,?) AND inArray IN () AND notInArray NOT IN (?,?,?) AND inSql IN (1,2,3,4,5) AND inSql NOT IN (1,2,3,4,5)) GROUP BY id,name,id2,name2 HAVING sum(age) > ? AND id is not null ORDER BY id ASC,name DESC,name2 DESC");
+        logSqlWhere("测试 Func 下的方法", queryWrapper, "(nullColumn IS NULL OR notNullColumn IS NOT NULL AND inColl IN (?,?) OR notInColl NOT IN (?,?) AND inArray IN () AND notInArray NOT IN (?,?,?) AND inSql IN (1,2,3,4,5) AND inSql NOT IN (1,2,3,4,5) AND gtSql > (1,2,3,4,5) AND ltSql < (1,2,3,4,5) AND geSql >= (1,2,3,4,5) AND leSql <= (1,2,3,4,5)) GROUP BY id,name,id2,name2 HAVING sum(age) > ? AND id is not null ORDER BY id ASC,name DESC,name2 DESC");
         logParams(queryWrapper);
     }
 

+ 25 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/conditions/AbstractChainWrapper.java

@@ -38,7 +38,7 @@ import java.util.function.Consumer;
  * @author miemie
  * @since 2018-12-19
  */
-@SuppressWarnings({"serial", "unchecked"})
+@SuppressWarnings({"unchecked"})
 public abstract class AbstractChainWrapper<T, R, Children extends AbstractChainWrapper<T, R, Children, Param>, Param extends AbstractWrapper<T, R, Param>>
     extends Wrapper<T> implements Compare<Children, R>, Func<Children, R>, Join<Children>, Nested<Param, Children> {
 
@@ -194,6 +194,30 @@ public abstract class AbstractChainWrapper<T, R, Children extends AbstractChainW
         return typedThis;
     }
 
+    @Override
+    public Children gtSql(boolean condition, R column, String inValue) {
+        getWrapper().gtSql(condition, column, inValue);
+        return typedThis;
+    }
+
+    @Override
+    public Children geSql(boolean condition, R column, String inValue) {
+        getWrapper().geSql(condition, column, inValue);
+        return typedThis;
+    }
+
+    @Override
+    public Children ltSql(boolean condition, R column, String inValue) {
+        getWrapper().ltSql(condition, column, inValue);
+        return typedThis;
+    }
+
+    @Override
+    public Children leSql(boolean condition, R column, String inValue) {
+        getWrapper().leSql(condition, column, inValue);
+        return typedThis;
+    }
+
     @Override
     public Children notInSql(boolean condition, R column, String inValue) {
         getWrapper().notInSql(condition, column, inValue);

+ 21 - 16
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java

@@ -21,6 +21,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.baomidou.mybatisplus.test.h2.entity.H2User;
@@ -118,22 +119,6 @@ class H2UserTest extends BaseTest {
         }
     }
 
-//    @Test
-//    void testQueryWithParamInSelectStatement4Page() {
-//        Map<String, Object> param = new HashMap<>();
-//        String nameParam = "selectStmtParam";
-//        param.put("nameParam", nameParam);
-//        param.put("ageFrom", 1);
-//        param.put("ageTo", 100);
-//        Page<H2User> page = userService.queryWithParamInSelectStatememt4Page(param, new Page<H2User>(0, 10));
-//        Assert.assertNotNull(page.getRecords());
-//        for (H2User u : page.getRecords()) {
-//            Assert.assertEquals(nameParam, u.getName());
-//            Assert.assertNotNull(u.getId());
-//        }
-//        Assert.assertNotEquals(0, pagemySelectMaps.getTotal());
-//    }
-
     @Test
     @Order(10)
     void testSelectCountWithParamInSelectItems() {
@@ -408,6 +393,26 @@ class H2UserTest extends BaseTest {
         }
     }
 
+    @Test
+    @Order(31)
+    void testSpaceCharacter() {
+        Assertions.assertFalse(StringUtils.isNotBlank(" "));
+        Assertions.assertTrue(StringUtils.checkValNotNull(" "));
+        H2User h2User = new H2User();
+        h2User.setName(" ");
+        Assertions.assertTrue(CollectionUtils.isEmpty(userService.list(new QueryWrapper<>(h2User)
+            .gt("age", 1).lt("age", 5))));
+    }
+
+    @Test
+    @Order(32)
+    void testSqlInjectionByCustomSqlSegment() {
+        // Preparing: select * from h2user WHERE (name LIKE ?)
+        // Parameters: %y%%(String)
+        List<H2User> h2Users = userService.testCustomSqlSegment(new QueryWrapper<H2User>().like("name", "y%"));
+        Assertions.assertTrue(2 == h2Users.size());
+    }
+
     @Test
     void myQueryWithGroupByOrderBy() {
         userService.mySelectMaps().forEach(System.out::println);

+ 5 - 12
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/mapper/H2UserMapper.java

@@ -15,7 +15,9 @@
  */
 package com.baomidou.mybatisplus.test.h2.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.test.h2.entity.H2Addr;
 import com.baomidou.mybatisplus.test.h2.entity.H2User;
@@ -66,22 +68,13 @@ public interface H2UserMapper extends SuperMapper<H2User> {
     )
     int myInsertWithoutParam(H2User user1);
 
-
     @Select(" select test_id as testId, power(#{ageFrom},2), 'abc?zhazha', CAST(#{nameParam} AS VARCHAR) as name " +
         " from h2user " +
         " where age>#{ageFrom} and age<#{ageTo} ")
     List<H2User> selectUserWithParamInSelectStatememt(Map<String, Object> param);
 
-//    @Select(" select test_id as id, power(#{ageFrom},2), 'abc?zhazha', CAST(#{nameParam} AS VARCHAR) as name " +
-//        " from h2user " +
-//        " where age>#{ageFrom} and age<#{ageTo} ")
-//    List<H2User> selectUserWithParamInSelectStatememt4Page(Map<String, Object> param, Page<H2User> page);
-//
-//    @Select(" select test_id as id, power(${ageFrom},2) as age, '${nameParam}' as name " +
-//        " from h2user " +
-//        " where age>#{ageFrom} and age<#{ageTo} ")
-//    List<H2User> selectUserWithDollarParamInSelectStatememt4Page(Map<String, Object> param, Page<H2User> page);
-
+    @Select("select * from h2user ${ew.customSqlSegment}")
+    List<H2User> selectTestCustomSqlSegment(@Param(Constants.WRAPPER) Wrapper wrapper);
 
     @Select("select count(1) from (" +
         "select test_id as id, CAST(#{nameParam} AS VARCHAR) as name" +
@@ -91,7 +84,7 @@ public interface H2UserMapper extends SuperMapper<H2User> {
     int selectCountWithParamInSelectItems(Map<String, Object> param);
 
     @Select("select age,name,count(age) from h2user group by age,name order by age")
-    List<Map<?,?>> mySelectMaps(IPage<H2User> page);
+    List<Map<?, ?>> mySelectMaps(IPage<H2User> page);
 
     @Select("call 1")
     @Options(statementType = StatementType.CALLABLE)

+ 3 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/service/IH2UserService.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.test.h2.service;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.test.h2.entity.H2User;
@@ -57,4 +58,6 @@ public interface IH2UserService extends IService<H2User> {
     void testSaveBatchNoTransactional1();
 
     void testSaveBatchNoTransactional2();
+
+    List<H2User> testCustomSqlSegment(Wrapper wrapper);
 }

+ 6 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/service/impl/H2UserServiceImpl.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.test.h2.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.OrderItem;
@@ -134,4 +135,9 @@ public class H2UserServiceImpl extends ServiceImpl<H2UserMapper, H2User> impleme
         save(new H2User(1577431655447L, "testSaveBatchNoTransactional2"));
         saveBatch(Arrays.asList(new H2User("testSaveBatchNoTransactional2", 0), new H2User("testSaveBatchNoTransactional2", 0), new H2User(1577431655447L, "testSaveBatchNoTransactional2")), 1);
     }
+
+    @Override
+    public List<H2User> testCustomSqlSegment(Wrapper wrapper) {
+        return baseMapper.selectTestCustomSqlSegment(wrapper);
+    }
 }