Browse Source

增强参数填充处理器,防止因类型不匹配导致转换错误.

https://github.com/baomidou/mybatis-plus/issues/5365
nieqiurong 2 năm trước cách đây
mục cha
commit
5412d3e52e

+ 19 - 4
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisParameterHandler.java

@@ -191,21 +191,36 @@ public class MybatisParameterHandler implements ParameterHandler {
             parameters = (Collection) parameterObject;
         } else if (parameterObject instanceof Map) {
             Map parameterMap = (Map) parameterObject;
+            // 约定 coll collection list array 这四个特殊key值处理批量.
             // 尝试提取参数进行填充,如果是多参数时,在使用注解时,请注意使用collection,list,array进行声明
             if (parameterMap.containsKey("collection")) {
-                parameters = (Collection) parameterMap.get("collection");
+                return toCollection(parameterMap.get("collection"));
             } else if (parameterMap.containsKey(Constants.COLL)) {
                 // 兼容逻辑删除对象填充,这里的集合字段后面重构的时候应该和原生保持一致,使用collection
-                parameters = (Collection) parameterMap.get(Constants.COLL);
+                parameters = toCollection(parameterMap.get(Constants.COLL));
             } else if (parameterMap.containsKey(Constants.LIST)) {
-                parameters = (List) parameterMap.get(Constants.LIST);
+                parameters = toCollection(parameterMap.get(Constants.LIST));
             } else if (parameterMap.containsKey(Constants.ARRAY)) {
-                parameters = Arrays.asList((Object[]) parameterMap.get(Constants.ARRAY));
+                parameters = toCollection(parameterMap.get(Constants.ARRAY));
             }
         }
         return parameters;
     }
 
+    @SuppressWarnings("unchecked")
+    protected Collection<Object> toCollection(Object value) {
+        if (value == null) {
+            return null;
+        }
+        // 只处理array和collection
+        if (value.getClass().isArray()) {
+            return Arrays.asList((Object[]) value);
+        } else if (Collection.class.isAssignableFrom(value.getClass())) {
+            return (Collection<Object>) value;
+        }
+        return null;
+    }
+
     @Override
     @SuppressWarnings("unchecked")
     public void setParameters(PreparedStatement ps) {

+ 11 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ArrayUtils.java

@@ -49,4 +49,15 @@ public final class ArrayUtils {
         return !isEmpty(array);
     }
 
+
+    /**
+     * 判断是否为数组
+     *
+     * @param obj 对象
+     * @return 是否为数组
+     */
+    public static boolean isArray(Object obj) {
+        return obj != null && obj.getClass().isArray();
+    }
+
 }

+ 109 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/MybatisParameterHandlerTest.java

@@ -23,6 +23,7 @@ import org.apache.ibatis.reflection.MetaObject;
 import org.apache.ibatis.session.Configuration;
 import org.junit.jupiter.api.Test;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -116,7 +117,115 @@ class MybatisParameterHandlerTest {
 //        Assertions.assertNotNull(model3.getInsertOperator());
 //        Assertions.assertNull(model3.getUpdateOperator());
 
+        params1 = new HashMap<>();
+        Model model1 = new Model();
+        Model model2 = new Model();
+        params1.put("arrays", new Model[]{model1, model2});
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+        assertThat(model1.getId()).isNull();
+        assertThat(model2.getId()).isNull();
+        assertThat(model1.getInsertOperator()).isNull();
+        assertThat(model1.getUpdateOperator()).isNull();
+
+        model1 = new Model();
+        model2 = new Model();
+        params1 = new HashMap<>();
+        params1.put(Constants.ARRAY, new Model[]{model1, model2});
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+        assertThat(model1.getId()).isNotNull();
+        assertThat(model2.getId()).isNotNull();
+        assertThat(model1.getInsertOperator()).isNotNull();
+        assertThat(model1.getUpdateOperator()).isNull();
+
+        model1 = new Model();
+        model2 = new Model();
+        params1 = new HashMap<>();
+        params1.put(Constants.ARRAY, new Object[]{model1, model2});
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+        assertThat(model1.getId()).isNotNull();
+        assertThat(model2.getId()).isNotNull();
+        assertThat(model1.getInsertOperator()).isNotNull();
+        assertThat(model1.getUpdateOperator()).isNull();
+
+
+        model1 = new Model();
+        model2 = new Model();
+        params1 = new HashMap<>();
+        params1.put(Constants.LIST, Arrays.asList(model1, model2));
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+        assertThat(model1.getId()).isNotNull();
+        assertThat(model2.getId()).isNotNull();
+        assertThat(model1.getInsertOperator()).isNotNull();
+        assertThat(model1.getUpdateOperator()).isNull();
+
+
+        model1 = new Model();
+        model2 = new Model();
+        params1 = new HashMap<>();
+        params1.put(Constants.COLL, Arrays.asList(model1, model2));
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+        assertThat(model1.getId()).isNotNull();
+        assertThat(model2.getId()).isNotNull();
+        assertThat(model1.getInsertOperator()).isNotNull();
+        assertThat(model1.getUpdateOperator()).isNull();
+
+        model1 = new Model();
+        model2 = new Model();
+        params1 = new HashMap<>();
+        params1.put("collection", Arrays.asList(model1, model2));
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+        assertThat(model1.getId()).isNotNull();
+        assertThat(model2.getId()).isNotNull();
+        assertThat(model1.getInsertOperator()).isNotNull();
+        assertThat(model1.getUpdateOperator()).isNull();
+
+
+        params1 = new HashMap<>();
+        params1.put(Constants.ARRAY, new Object());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1.put(Constants.ARRAY, new HashMap<>());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1.put(Constants.ARRAY, new Object[]{});
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
 
+        params1.put(Constants.ARRAY, null);
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+
+        params1 = new HashMap<>();
+        params1.put(Constants.COLL, new Object());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1 = new HashMap<>();
+        params1.put(Constants.COLL, new HashMap<>());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1.put(Constants.COLL, null);
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1.put(Constants.COLL, new ArrayList<>());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1 = new HashMap<>();
+        params1.put("collection", new Object());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1 = new HashMap<>();
+        params1.put("collection", new Object());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1 = new HashMap<>();
+        params1.put("collection", new HashMap<>());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1.put("collection", null);
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
+
+        params1.put("collection", new ArrayList<>());
+        new MybatisParameterHandler(mappedStatement, params1, boundSql);
         //普通更新
         model = new Model(1L, "坦克");
         mappedStatement = new MappedStatement.Builder(configuration, "***", staticSqlSource, SqlCommandType.UPDATE).build();