Browse Source

Merge pull request #5451 from nieqiurong/20230706181729

填充器单参数数组支持无注解填充,支持多参数填充
qmdx 1 year ago
parent
commit
32a4aa8751

+ 43 - 10
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisParameterHandler.java

@@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
@@ -38,8 +39,10 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -51,6 +54,8 @@ import java.util.Map;
  */
 public class MybatisParameterHandler implements ParameterHandler {
 
+    public static final String[] COLLECTION_KEYS = new String[]{"collection", "coll", "list", "array"};
+
     private final TypeHandlerRegistry typeHandlerRegistry;
     private final MappedStatement mappedStatement;
     private final Object parameterObject;
@@ -75,13 +80,7 @@ public class MybatisParameterHandler implements ParameterHandler {
             if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
                 return parameter;
             }
-            Collection<Object> parameters = getParameters(parameter);
-            if (null != parameters) {
-                // 感觉这里可以稍微优化一下,理论上都是同一个.
-                parameters.forEach(this::process);
-            } else {
-                process(parameter);
-            }
+            extractParameters(parameter).forEach(this::process);
         }
         return parameter;
     }
@@ -183,12 +182,16 @@ public class MybatisParameterHandler implements ParameterHandler {
      * </p>
      *
      * @return 集合参数
+     * @deprecated 3.5.3
      */
     @SuppressWarnings({"rawtypes", "unchecked"})
+    @Deprecated
     protected Collection<Object> getParameters(Object parameterObject) {
         Collection<Object> parameters = null;
         if (parameterObject instanceof Collection) {
             parameters = (Collection) parameterObject;
+        } else if (ArrayUtils.isArray(parameterObject)) {
+            parameters = toCollection(parameterObject);
         } else if (parameterObject instanceof Map) {
             Map parameterMap = (Map) parameterObject;
             // 约定 coll collection list array 这四个特殊key值处理批量.
@@ -207,18 +210,48 @@ public class MybatisParameterHandler implements ParameterHandler {
         return parameters;
     }
 
+    /**
+     * 提取特殊key值 (只支持外层参数,嵌套参数不考虑)
+     * List<Map>虽然这种写法目前可以进去提取et,但不考虑再提取list等其他类型,只做简单参数提取
+     *
+     * @param parameterObject 参数
+     * @return 预期可能为填充参数值
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private Collection<Object> extractParameters(Object parameterObject) {
+        Collection<Object> parameters = new ArrayList<>();
+        if (parameterObject instanceof Collection) {
+            parameters = (Collection) parameterObject;
+        } else if (ArrayUtils.isArray(parameterObject)) {
+            parameters = toCollection(parameterObject);
+        } else if (parameterObject instanceof Map) {
+            Map parameterMap = (Map) parameterObject;
+            if (parameterMap.containsKey(Constants.ENTITY)) {
+                parameters.add(parameterMap.get(Constants.ENTITY));
+            }
+            for (String key : COLLECTION_KEYS) {
+                if (parameterMap.containsKey(key)) {
+                    parameters.addAll(toCollection(parameterMap.get(key)));
+                }
+            }
+        } else {
+            parameters.add(parameterObject);
+        }
+        return parameters;
+    }
+
     @SuppressWarnings("unchecked")
     protected Collection<Object> toCollection(Object value) {
         if (value == null) {
-            return null;
+            return Collections.emptyList();
         }
         // 只处理array和collection
-        if (value.getClass().isArray()) {
+        if (ArrayUtils.isArray(value)) {
             return Arrays.asList((Object[]) value);
         } else if (Collection.class.isAssignableFrom(value.getClass())) {
             return (Collection<Object>) value;
         }
-        return null;
+        return Collections.emptyList();
     }
 
     @Override

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

@@ -253,6 +253,23 @@ class MybatisParameterHandlerTest {
             assertThat(m.getInsertOperator()).isNotNull();
             assertThat(m.getUpdateOperator()).isNotNull();
         });
+
+        Model[] arrays = new Model[]{new Model("坦克一号"), new Model("坦克二号")};
+        mappedStatement = new MappedStatement.Builder(configuration, "***", staticSqlSource, SqlCommandType.INSERT).build();
+        new MybatisParameterHandler(mappedStatement, arrays, boundSql);
+        Arrays.stream(arrays).forEach(m -> {
+            assertThat(m.getId()).isNotNull();
+            assertThat(m.getInsertOperator()).isNotNull();
+            assertThat(m.getUpdateOperator()).isNull();
+        });
+
+        mappedStatement = new MappedStatement.Builder(configuration, "***", staticSqlSource, SqlCommandType.UPDATE).build();
+        new MybatisParameterHandler(mappedStatement, arrays, boundSql);
+        Arrays.stream(arrays).forEach(m -> {
+            assertThat(m.getId()).isNotNull();
+            assertThat(m.getInsertOperator()).isNotNull();
+            assertThat(m.getUpdateOperator()).isNotNull();
+        });
     }
 
 }

+ 97 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java

@@ -30,6 +30,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.test.h2.entity.H2User;
 import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
+import com.baomidou.mybatisplus.test.h2.mapper.H2StudentMapper;
 import com.baomidou.mybatisplus.test.h2.service.IH2UserService;
 import net.sf.jsqlparser.parser.CCJSqlParserUtil;
 import net.sf.jsqlparser.statement.select.Select;
@@ -73,6 +74,9 @@ class H2UserTest extends BaseTest {
     @Autowired
     SqlSessionFactory sqlSessionFactory;
 
+    @Autowired
+    private H2StudentMapper h2StudentMapper;
+
     public void initBatchLimitation(int limitation) {
         if (sqlSessionFactory instanceof DefaultSqlSessionFactory) {
             Configuration configuration = sqlSessionFactory.getConfiguration();
@@ -674,4 +678,97 @@ class H2UserTest extends BaseTest {
         Assertions.assertThrows(TooManyResultsException.class, () -> userService.getOneOpt(Wrappers.<H2User>lambdaQuery()
             .like(H2User::getName, "tes")));
     }
+
+    @Test
+    void testInsertFill() {
+        H2User h2User;
+        h2User = new H2User("insertFillByCustomMethod1", AgeEnum.ONE);
+        h2StudentMapper.insertFillByCustomMethod1(h2User);
+        Assertions.assertNotNull(h2User.getTestType());
+
+        h2User = new H2User("insertFillByCustomMethod2", AgeEnum.ONE);
+        h2StudentMapper.insertFillByCustomMethod2(h2User);
+        Assertions.assertNotNull(h2User.getTestType());
+
+        h2User = new H2User("insertFillByCustomMethod3", AgeEnum.ONE);
+        h2StudentMapper.insertFillByCustomMethod3(h2User, "fillByCustomMethod3");
+        Assertions.assertNotNull(h2User.getTestType());
+
+        List<H2User> list;
+        list = Arrays.asList(new H2User("insertFillByCustomMethod4-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod4-2", AgeEnum.ONE));
+        h2StudentMapper.insertFillByCustomMethod4(list);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        list = Arrays.asList(new H2User("insertFillByCustomMethod5-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod5-2", AgeEnum.ONE));
+        h2StudentMapper.insertFillByCustomMethod5(list);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        list = Arrays.asList(new H2User("insertFillByCustomMethod6-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod6-2", AgeEnum.ONE));
+        h2StudentMapper.insertFillByCustomMethod6(list);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        list = Arrays.asList(new H2User("insertFillByCustomMethod7-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod7-2", AgeEnum.ONE));
+        h2StudentMapper.insertFillByCustomMethod7(list);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        H2User[] h2Users;
+        h2Users = new H2User[]{new H2User("insertFillByCustomMethod8-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod8-2", AgeEnum.ONE)};
+        h2StudentMapper.insertFillByCustomMethod8(h2Users);
+        Arrays.stream(h2Users).forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        h2Users = new H2User[]{new H2User("insertFillByCustomMethod9-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod9-2", AgeEnum.ONE)};
+        h2StudentMapper.insertFillByCustomMethod9(h2Users);
+        Arrays.stream(h2Users).forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        Map<String, Object> map;
+        h2User = new H2User("insertFillByCustomMethod10", AgeEnum.ONE);
+        map = new HashMap<>();
+        map.put("et", h2User);
+        h2StudentMapper.insertFillByCustomMethod10(map);
+        Assertions.assertNotNull(h2User.getTestType());
+
+        list = Arrays.asList(new H2User("insertFillByCustomMethod11-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod11-2", AgeEnum.ONE));
+        map = new HashMap<>();
+        map.put("list", list);
+        h2StudentMapper.insertFillByCustomMethod11(map);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        list = Arrays.asList(new H2User("insertFillByCustomMethod12-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod12-2", AgeEnum.ONE));
+        map = new HashMap<>();
+        map.put("coll", list);
+        h2StudentMapper.insertFillByCustomMethod12(map);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+
+        h2Users = new H2User[]{new H2User("insertFillByCustomMethod13-1", AgeEnum.ONE), new H2User("insertFillByCustomMethod13-2", AgeEnum.ONE)};
+        map = new HashMap<>();
+        map.put("array", h2Users);
+        h2StudentMapper.insertFillByCustomMethod13(map);
+        list.forEach(user -> Assertions.assertNotNull(user.getTestType()));
+    }
+
+    @Test
+    void testUpdateFill(){
+        Map<String, Object> map;
+        H2User h2User;
+        h2User = new H2User();
+        map = new HashMap<>();
+        map.put("et", h2User);
+        map.put("list", Arrays.asList(1L, 2L, 3L));
+        h2StudentMapper.updateFillByCustomMethod1(map);
+        Assertions.assertNotNull(h2User.getLastUpdatedDt());
+
+        h2User = new H2User();
+        h2StudentMapper.updateFillByCustomMethod2(Arrays.asList(1L, 2L, 3L), h2User);
+        Assertions.assertNotNull(h2User.getLastUpdatedDt());
+
+        h2User = new H2User();
+        h2StudentMapper.updateFillByCustomMethod3(Arrays.asList(1L, 2L, 3L), h2User);
+        Assertions.assertNull(h2User.getLastUpdatedDt());
+
+        h2User = new H2User();
+        h2StudentMapper.updateFillByCustomMethod4(Arrays.asList(1L, 2L, 3L), h2User);
+        Assertions.assertNotNull(h2User.getLastUpdatedDt());
+
+    }
+
 }

+ 2 - 1
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/H2User.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.test.h2.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -53,7 +54,7 @@ public class H2User extends SuperEntity {
     private BigDecimal price;
 
     /* 测试下划线字段命名类型, 字段填充 */
-    @TableField
+    @TableField(fill = FieldFill.INSERT)
     private Integer testType;
 
     /**

+ 43 - 1
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/mapper/H2StudentMapper.java

@@ -16,9 +16,51 @@
 package com.baomidou.mybatisplus.test.h2.mapper;
 
 import com.baomidou.mybatisplus.test.h2.entity.H2Student;
+import com.baomidou.mybatisplus.test.h2.entity.H2User;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 学生Mapper层
  * @author nieqiurong 2018/7/27.
  */
-public interface H2StudentMapper extends SuperMapper<H2Student> {}
+public interface H2StudentMapper extends SuperMapper<H2Student> {
+
+    long insertFillByCustomMethod1(H2User h2User);
+
+    long insertFillByCustomMethod2(@Param("et") H2User h2User);
+
+    long insertFillByCustomMethod3(@Param("et") H2User h2User, @Param("test") String test);
+
+    long insertFillByCustomMethod4(Collection<H2User> h2User);
+
+    long insertFillByCustomMethod5(@Param("collection") Collection<H2User> h2User);
+
+    long insertFillByCustomMethod6(@Param("coll") Collection<H2User> h2User);
+
+    long insertFillByCustomMethod7(@Param("list") List<H2User> h2User);
+
+    long insertFillByCustomMethod8(H2User[] h2Users);
+
+    long insertFillByCustomMethod9(@Param("array") H2User[] h2Users);
+
+    long insertFillByCustomMethod10(Map<String, Object> paramMap);
+
+    long insertFillByCustomMethod11(Map<String, Object> paramMap);
+
+    long insertFillByCustomMethod12(Map<String, Object> paramMap);
+
+    long insertFillByCustomMethod13(Map<String, Object> paramMap);
+
+    long updateFillByCustomMethod1(Map<String, Object> paramMap);
+
+    long updateFillByCustomMethod2(@Param("coll") Collection<Long> ids, @Param("et") H2User h2User);
+
+    long updateFillByCustomMethod3(@Param("coll") Collection<Long> ids, @Param("user") H2User h2User);
+
+    long updateFillByCustomMethod4(@Param("colls") Collection<Long> ids, @Param("et") H2User h2User);
+
+}

+ 121 - 0
mybatis-plus/src/test/resources/com/baomidou/mybatisplus/test/h2/mapper/H2StudentMapper.xml

@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.baomidou.mybatisplus.test.h2.mapper.H2StudentMapper">
+
+    <insert id="insertFillByCustomMethod1">
+        insert into h2user(test_id, name, age, test_type)
+        values (#{testId}, #{name}, #{age}, #{testType})
+    </insert>
+
+    <insert id="insertFillByCustomMethod2">
+        insert into h2user(test_id, name, age, test_type)
+        values (#{et.testId}, #{et.name}, #{et.age}, #{et.testType})
+    </insert>
+
+    <insert id="insertFillByCustomMethod3">
+        insert into h2user(test_id, name, age, test_type)
+        values (#{et.testId}, #{test}, #{et.age}, #{et.testType})
+    </insert>
+
+    <insert id="insertFillByCustomMethod4">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="collection" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod5">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="collection" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod6">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="coll" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod7">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="list" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod8">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="array" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod9">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="array" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod10">
+        insert into h2user(test_id, name, age, test_type)
+        values (#{et.testId}, #{et.name}, #{et.age}, #{et.testType})
+    </insert>
+
+    <insert id="insertFillByCustomMethod11">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="list" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+
+    <insert id="insertFillByCustomMethod12">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="coll" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <insert id="insertFillByCustomMethod13">
+        insert into h2user(test_id, name, age, test_type) values
+        <foreach collection="array" item="col" separator=",">
+            (#{col.testId}, #{col.name}, #{col.age}, #{col.testType})
+        </foreach>
+    </insert>
+
+    <update id="updateFillByCustomMethod1">
+        update h2user set deleted = 1,last_updated_dt = #{et.lastUpdatedDt} where test_id in (
+        <foreach collection="list" item="col" separator=",">
+            #{col}
+        </foreach>
+        )
+    </update>
+
+    <update id="updateFillByCustomMethod2">
+        update h2user set deleted = 1,last_updated_dt = #{et.lastUpdatedDt} where test_id in (
+        <foreach collection="coll" item="col" separator=",">
+            #{col}
+        </foreach>
+        )
+    </update>
+
+    <update id="updateFillByCustomMethod3">
+        update h2user set deleted = 1,last_updated_dt = #{user.lastUpdatedDt} where test_id in (
+        <foreach collection="coll" item="col" separator=",">
+            #{col}
+        </foreach>
+        )
+    </update>
+
+    <update id="updateFillByCustomMethod4">
+        update h2user set deleted = 1,last_updated_dt = #{et.lastUpdatedDt} where test_id in (
+        <foreach collection="colls" item="col" separator=",">
+            #{col}
+        </foreach>
+        )
+    </update>
+
+</mapper>