Explorar o código

新增选装件的 InsertBatch 通用方法,以及相应测试,以及代码和性能的优化

miemie %!s(int64=6) %!d(string=hai) anos
pai
achega
35f80083d8

+ 4 - 33
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisDefaultParameterHandler.java

@@ -29,7 +29,6 @@ import org.apache.ibatis.type.TypeException;
 import org.apache.ibatis.type.TypeHandler;
 import org.apache.ibatis.type.TypeHandlerRegistry;
 
-import java.lang.reflect.Field;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.util.*;
@@ -45,10 +44,6 @@ import java.util.*;
  */
 public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
 
-    /**
-     * @see BoundSql
-     */
-    private static final Field ADDITIONAL_PARAMETERS_FIELD = getAdditionalParametersField();
     private final TypeHandlerRegistry typeHandlerRegistry;
     private final MappedStatement mappedStatement;
     private final Object parameterObject;
@@ -64,29 +59,12 @@ public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
         this.boundSql = boundSql;
     }
 
-    /**
-     * 反射获取BoundSql中additionalParameters参数字段
-     *
-     * @return additionalParameters 字段
-     * @see BoundSql
-     */
-    private static Field getAdditionalParametersField() {
-        try {
-            Field additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
-            additionalParametersField.setAccessible(true);
-            return additionalParametersField;
-        } catch (NoSuchFieldException e) {
-            // ignored, Because it will never happen.
-        }
-        return null;
-    }
-
     /**
      * <p>
      * 批量(填充主键 ID)
      * </p>
      *
-     * @param ms MappedStatement
+     * @param ms              MappedStatement
      * @param parameterObject 插入数据库对象
      * @return
      */
@@ -227,15 +205,8 @@ public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
     }
 
     @Override
-    @SuppressWarnings({"rawtypes", "unchecked"})
+    @SuppressWarnings("unchecked")
     public void setParameters(PreparedStatement ps) {
-        // 反射获取动态参数
-        Map<String, Object> additionalParameters = Collections.emptyMap();
-        try {
-            additionalParameters = (Map<String, Object>) ADDITIONAL_PARAMETERS_FIELD.get(boundSql);
-        } catch (IllegalAccessException e) {
-            // ignored, Because it will never happen.
-        }
         ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
         List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
         if (parameterMappings != null) {
@@ -244,8 +215,8 @@ public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
                 if (parameterMapping.getMode() != ParameterMode.OUT) {
                     Object value;
                     String propertyName = parameterMapping.getProperty();
-                    if (boundSql.hasAdditionalParameter(propertyName)) {
-                        value = additionalParameters.get(propertyName);
+                    if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
+                        value = boundSql.getAdditionalParameter(propertyName);
                     } else if (parameterObject == null) {
                         value = null;
                     } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {

+ 3 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/injector/methods/Insert.java

@@ -37,15 +37,16 @@ import org.apache.ibatis.mapping.SqlSource;
  * @author hubin
  * @since 2018-04-06
  */
+@SuppressWarnings("all")
 public class Insert extends AbstractMethod {
 
     @Override
     public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
         KeyGenerator keyGenerator = new NoKeyGenerator();
         SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
-        String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumn(),
+        String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumn(false),
             StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET, null, StringPool.COMMA);
-        String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlProperty(),
+        String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlProperty(false, null),
             StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET, null, StringPool.COMMA);
         String keyProperty = null;
         String keyColumn = null;

+ 11 - 10
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableFieldInfo.java

@@ -239,30 +239,31 @@ public class TableFieldInfo {
     }
 
     /**
-     * 获取 inset 时候插入值 sql 脚本片段
+     * 获取 insert 时候插入值 sql 脚本片段
      * insert into table (字段) values (值)
      * 位于 "值" 部位
      *
      * @return sql 脚本片段
      */
-    public String getInsertSqlProperty() {
-        String sqlScript = SqlScriptUtils.safeParam(el) + StringPool.COMMA;
-        if (fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) {
+    public String getInsertSqlProperty(boolean isAll, final String prefix) {
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
+        String sqlScript = SqlScriptUtils.safeParam(newPrefix + el) + StringPool.COMMA;
+        if (isAll || fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) {
             return sqlScript;
         }
         return convertIf(sqlScript, property);
     }
 
     /**
-     * 获取 inset 时候字段 sql 脚本片段
+     * 获取 insert 时候字段 sql 脚本片段
      * insert into table (字段) values (值)
      * 位于 "字段" 部位
      *
      * @return sql 脚本片段
      */
-    public String getInsertSqlColumn() {
-        String sqlScript = column + StringPool.COMMA;
-        if (fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) {
+    public String getInsertSqlColumn(boolean isAll) {
+        final String sqlScript = column + StringPool.COMMA;
+        if (isAll || fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) {
             return sqlScript;
         }
         return convertIf(sqlScript, property);
@@ -275,7 +276,7 @@ public class TableFieldInfo {
      * @return sql 脚本片段
      */
     public String getSqlSet(final String prefix) {
-        String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
         // 默认: column=
         String sqlSet = column + StringPool.EQUALS;
         if (StringUtils.isNotEmpty(update)) {
@@ -298,7 +299,7 @@ public class TableFieldInfo {
      * @return sql 脚本片段
      */
     public String getSqlWhere(final String prefix) {
-        String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
         // 默认:  AND column=#{prefix + el}
         String sqlScript = " AND " + String.format(condition, column, newPrefix + el);
         // 查询的时候只判非空

+ 16 - 12
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfo.java

@@ -198,12 +198,13 @@ public class TableInfo {
      *
      * @return sql 脚本片段
      */
-    public String getKeyInsertSqlProperty() {
+    public String getKeyInsertSqlProperty(final String prefix, final String delimiter) {
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
         if (StringUtils.isNotEmpty(keyProperty)) {
             if (idType == IdType.AUTO) {
                 return StringPool.EMPTY;
             }
-            return SqlScriptUtils.safeParam(keyProperty) + StringPool.COMMA + StringPool.NEWLINE;
+            return SqlScriptUtils.safeParam(newPrefix + keyProperty) + StringPool.COMMA + delimiter;
         }
         return StringPool.EMPTY;
     }
@@ -215,12 +216,12 @@ public class TableInfo {
      *
      * @return sql 脚本片段
      */
-    public String getKeyInsertSqlColumn() {
+    public String getKeyInsertSqlColumn(final String delimiter) {
         if (StringUtils.isNotEmpty(keyColumn)) {
             if (idType == IdType.AUTO) {
                 return StringPool.EMPTY;
             }
-            return keyColumn + StringPool.COMMA + StringPool.NEWLINE;
+            return keyColumn + StringPool.COMMA + delimiter;
         }
         return StringPool.EMPTY;
     }
@@ -233,9 +234,11 @@ public class TableInfo {
      *
      * @return sql 脚本片段
      */
-    public String getAllInsertSqlProperty() {
-        return getKeyInsertSqlProperty() + fieldList.stream().map(TableFieldInfo::getInsertSqlProperty)
-            .collect(joining(StringPool.NEWLINE));
+    public String getAllInsertSqlProperty(boolean isAll, final String prefix) {
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
+        final String delimiter = isAll ? StringPool.EMPTY : StringPool.NEWLINE;
+        return getKeyInsertSqlProperty(newPrefix, delimiter) + fieldList.stream()
+            .map(i -> i.getInsertSqlProperty(isAll, newPrefix)).collect(joining(delimiter));
     }
 
     /**
@@ -245,9 +248,10 @@ public class TableInfo {
      *
      * @return sql 脚本片段
      */
-    public String getAllInsertSqlColumn() {
-        return getKeyInsertSqlColumn() + fieldList.stream().map(TableFieldInfo::getInsertSqlColumn)
-            .collect(joining(StringPool.NEWLINE));
+    public String getAllInsertSqlColumn(boolean isAll) {
+        final String delimiter = isAll ? StringPool.EMPTY : StringPool.NEWLINE;
+        return getKeyInsertSqlColumn(delimiter) + fieldList.stream().map(i -> i.getInsertSqlColumn(isAll))
+            .collect(joining(delimiter));
     }
 
     /**
@@ -259,7 +263,7 @@ public class TableInfo {
      * @return sql 脚本片段
      */
     public String getAllSqlWhere(boolean ignoreLogicDelFiled, boolean withId, final String prefix) {
-        String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
         String filedSqlScript = fieldList.stream()
             .filter(i -> {
                 if (ignoreLogicDelFiled) {
@@ -285,7 +289,7 @@ public class TableInfo {
      * @return sql 脚本片段
      */
     public String getAllSqlSet(boolean ignoreLogicDelFiled, final String prefix) {
-        String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
+        final String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
         return fieldList.stream()
             .filter(i -> {
                 if (ignoreLogicDelFiled) {

+ 71 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/additional/InsertBatch.java

@@ -0,0 +1,71 @@
+package com.baomidou.mybatisplus.extension.injector.methods.additional;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
+import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
+import org.apache.ibatis.executor.keygen.KeyGenerator;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+
+/**
+ * <p> 批量新增数据,全字段 insert </p>
+ * <p> 不同的数据库支持度不一样!!!  只在 mysql 下测试过!!!  只在 mysql 下测试过!!!  只在 mysql 下测试过!!! </p>
+ * <p> 除了主键是 <strong> 数据库自增的 </strong> 理论上都可以使用!!! </p>
+ * <p> 如果你使用自增有报错或主键值无法回写到entity,就不要跑来问为什么了,因为我也不知道!!! </p>
+ * <p>
+ * 自己的通用 mapper 如下使用:
+ * int insertBatch(List<T> entityList);
+ * 注意: 不要加任何注解!!!
+ * </p>
+ *
+ * @author miemie
+ * @since 2018-11-09
+ */
+@SuppressWarnings("all")
+public class InsertBatch extends AbstractMethod {
+
+    /**
+     * mapper 对应的方法名
+     */
+    private static final String MAPPER_METHOD = "insertBatch";
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        KeyGenerator keyGenerator = new NoKeyGenerator();
+        SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
+        String insertSqlColumn = tableInfo.getAllInsertSqlColumn(true);
+        String columnScript = StringPool.LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1)
+            + StringPool.RIGHT_BRACKET;
+        String insertSqlProperty = tableInfo.getAllInsertSqlProperty(true, Constants.ENTITY_SPOT);
+        insertSqlProperty = StringPool.LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + StringPool.RIGHT_BRACKET;
+        String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, Constants.ENTITY, StringPool.COMMA);
+        String keyProperty = null;
+        String keyColumn = null;
+        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
+        if (StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
+            if (tableInfo.getIdType() == IdType.AUTO) {
+                /** 自增主键 */
+                keyGenerator = new Jdbc3KeyGenerator();
+                keyProperty = tableInfo.getKeyProperty();
+                keyColumn = tableInfo.getKeyColumn();
+            } else {
+                if (null != tableInfo.getKeySequence()) {
+                    keyGenerator = TableInfoHelper.genKeyGenerator(tableInfo, builderAssistant, sqlMethod.getMethod(), languageDriver);
+                    keyProperty = tableInfo.getKeyProperty();
+                    keyColumn = tableInfo.getKeyColumn();
+                }
+            }
+        }
+        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        return this.addInsertMappedStatement(mapperClass, modelClass, MAPPER_METHOD, sqlSource, keyGenerator, keyProperty, keyColumn);
+    }
+}

+ 4 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/base/mapper/MyBaseMapper.java

@@ -2,6 +2,8 @@ package com.baomidou.mybatisplus.test.base.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
+import java.util.List;
+
 /**
  * @author miemie
  * @since 2018-09-13
@@ -9,4 +11,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 public interface MyBaseMapper<T> extends BaseMapper<T> {
 
     int deleteByIdWithFill(T entity);
+
+    int insertBatch(List<T> entityList);
 }

+ 10 - 4
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/mysql/MysqlTestDataMapperTest.java

@@ -24,10 +24,7 @@ import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import javax.annotation.Resource;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 
 /**
@@ -293,4 +290,13 @@ public class MysqlTestDataMapperTest {
         System.out.println(page.getTotal());
         System.out.println(page.getRecords().size());
     }
+
+    @Test
+    public void insertBatch() {
+        List<MysqlData> list = new ArrayList<>();
+        for (int i = 0; i < 9; i++) {
+            list.add(new MysqlData().setOrder(i).setGroup(i).setTestStr(i + "条"));
+        }
+        System.out.println(mysqlMapper.insertBatch(list));
+    }
 }

+ 2 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/mysql/config/MybatisPlusConfig.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.parser.ISqlParser;
 import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
+import com.baomidou.mybatisplus.extension.injector.methods.additional.InsertBatch;
 import com.baomidou.mybatisplus.extension.injector.methods.additional.LogicDeleteByIdWithFill;
 import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
@@ -73,6 +74,7 @@ public class MybatisPlusConfig {
             public List<AbstractMethod> getMethodList() {
                 List<AbstractMethod> methodList = super.getMethodList();
                 methodList.add(new LogicDeleteByIdWithFill());
+                methodList.add(new InsertBatch());
                 return methodList;
             }
         };