miemie 5 年之前
父節點
當前提交
f62a55e7fe

+ 116 - 50
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/MetaObjectHandler.java

@@ -23,8 +23,11 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.reflection.MetaObject;
 import org.apache.ibatis.reflection.SystemMetaObject;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Supplier;
 
 /**
  * 元对象字段填充控制器抽象类,实现公共字段自动写入
@@ -93,7 +96,9 @@ public interface MetaObjectHandler {
      * @param fieldVal   java bean property value
      * @param metaObject meta object parameter
      * @since 3.0.7
+     * @deprecated 3.2.1 please use {@link #strictInsertFill}
      */
+    @Deprecated
     default MetaObjectHandler setInsertFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {
         return setFieldValByName(fieldName, fieldVal, metaObject, FieldFill.INSERT);
     }
@@ -105,7 +110,9 @@ public interface MetaObjectHandler {
      * @param fieldVal   java bean property value
      * @param metaObject meta object parameter
      * @since 3.0.7
+     * @deprecated 3.2.1 please use {@link #strictUpdateFill}
      */
+    @Deprecated
     default MetaObjectHandler setUpdateFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {
         return setFieldValByName(fieldName, fieldVal, metaObject, FieldFill.UPDATE);
     }
@@ -119,7 +126,9 @@ public interface MetaObjectHandler {
      * @param metaObject meta object parameter
      * @param fieldFill  填充策略枚举
      * @since 3.0.7
+     * @deprecated 3.2.1 please use like {@link #strictInsertFill} or {@link #strictUpdateFill}
      */
+    @Deprecated
     default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject, FieldFill fieldFill) {
         if (Objects.nonNull(fieldVal)) {
             if (metaObject.hasSetter(fieldName) && metaObject.hasGetter(fieldName)
@@ -138,6 +147,38 @@ public interface MetaObjectHandler {
         return this;
     }
 
+    /**
+     * 填充判断
+     * <li> 如果是主键,不填充 </li>
+     * <li> 根据字段名找不到字段,不填充 </li>
+     * <li> 字段类型与填充值类型不匹配,不填充 </li>
+     * <li> 字段类型需在TableField注解里配置fill: @TableField(value="test_type", fill = FieldFill.INSERT), 没有配置或者不匹配时不填充 </li>
+     * v_3.1.0以后的版本(不包括3.1.0),子类的值也可以自动填充,Timestamp的值也可以填入到java.util.Date类型里面
+     *
+     * @param fieldName  java bean property name
+     * @param fieldVal   java bean property value
+     * @param metaObject meta object parameter
+     * @param fieldFill  填充策略枚举
+     * @return 是否进行填充
+     * @since 3.0.7
+     * @deprecated 3.2.1
+     */
+    @Deprecated
+    default boolean isFill(String fieldName, Object fieldVal, MetaObject metaObject, FieldFill fieldFill) {
+        TableInfo tableInfo = findTableInfo(metaObject);
+        if (Objects.nonNull(tableInfo)) {
+            Optional<TableFieldInfo> first = tableInfo.getFieldList().stream()
+                //v_3.1.1+ 设置子类的值也可以通过
+                .filter(e -> e.getProperty().equals(fieldName) && e.getPropertyType().isAssignableFrom(fieldVal.getClass()))
+                .findFirst();
+            if (first.isPresent()) {
+                FieldFill fill = first.get().getFieldFill();
+                return fill.equals(fieldFill) || FieldFill.INSERT_UPDATE.equals(fill);
+            }
+        }
+        return false;
+    }
+
     /**
      * get value from java bean by propertyName
      * <p>如果包含前缀 et 使用该方法,否则可以直接 metaObject.setValue(fieldName, fieldVal);</p>
@@ -156,78 +197,103 @@ public interface MetaObjectHandler {
     }
 
     /**
-     * check if the entity has some property will fill for insert </p>
-     * 表字段是否启用了插入填充
+     * find the tableInfo cache by metaObject </p>
+     * 获取 TableInfo 缓存
      *
+     * @param metaObject meta object parameter
+     * @return TableInfo
+     * @since 3.2.1
+     */
+    default TableInfo findTableInfo(MetaObject metaObject) {
+        return metaObject.hasGetter(Constants.MP_OPTLOCK_ET_ORIGINAL) ?
+            TableInfoHelper.getTableInfo(metaObject.getValue(Constants.MP_OPTLOCK_ET_ORIGINAL).getClass())
+            : TableInfoHelper.getTableInfo(metaObject.getOriginalObject().getClass());
+    }
+
+    /**
      * @param metaObject metaObject meta object parameter
-     * @return yes or no
      * @since 3.2.1
      */
-    default boolean isWithInsertFill(MetaObject metaObject) {
-        TableInfo tableInfo = findTableInfo(metaObject);
-        if (Objects.nonNull(tableInfo)) {
-            return tableInfo.isWithInsertFill();
-        }
-        return false;
+    default <T> MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class<T> fieldType, Object fieldVal) {
+        return strictInsertFill(findTableInfo(metaObject), metaObject, Collections.singletonList(StrictFill.of(fieldName, fieldType, fieldVal)));
     }
 
     /**
-     * check if the entity has some property will fill for update </p>
-     * 表字段是否启用了更新填充
-     *
      * @param metaObject metaObject meta object parameter
-     * @return yes or no
      * @since 3.2.1
      */
-    default boolean isWithUpdateFill(MetaObject metaObject) {
-        TableInfo tableInfo = findTableInfo(metaObject);
-        if (Objects.nonNull(tableInfo)) {
-            return tableInfo.isWithUpdateFill();
-        }
-        return false;
+    default <T> MetaObjectHandler strictInsertFill(MetaObject metaObject, String fieldName, Class<T> fieldType, Supplier<T> fieldVal) {
+        return strictInsertFill(findTableInfo(metaObject), metaObject, Collections.singletonList(StrictFill.of(fieldName, fieldType, fieldVal)));
     }
 
     /**
-     * find the tableInfo cache by metaObject </p>
-     * 获取 TableInfo 缓存
+     * @param metaObject metaObject meta object parameter
+     * @since 3.2.1
+     */
+    default MetaObjectHandler strictInsertFill(TableInfo tableInfo, MetaObject metaObject, List<StrictFill> strictFills) {
+        return strictFill(true, tableInfo, metaObject, strictFills);
+    }
+
+    /**
+     * @param metaObject metaObject meta object parameter
+     * @since 3.2.1
+     */
+    default <T> MetaObjectHandler strictUpdateFill(MetaObject metaObject, String fieldName, Class<T> fieldType, Supplier<T> fieldVal) {
+        return strictUpdateFill(findTableInfo(metaObject), metaObject, Collections.singletonList(StrictFill.of(fieldName, fieldType, fieldVal)));
+    }
+
+    /**
+     * @param metaObject metaObject meta object parameter
+     * @since 3.2.1
+     */
+    default <T> MetaObjectHandler strictUpdateFill(MetaObject metaObject, String fieldName, Class<T> fieldType, Object fieldVal) {
+        return strictUpdateFill(findTableInfo(metaObject), metaObject, Collections.singletonList(StrictFill.of(fieldName, fieldType, fieldVal)));
+    }
+
+    /**
+     * @param metaObject metaObject meta object parameter
+     * @since 3.2.1
+     */
+    default MetaObjectHandler strictUpdateFill(TableInfo tableInfo, MetaObject metaObject, List<StrictFill> strictFills) {
+        return strictFill(false, tableInfo, metaObject, strictFills);
+    }
+
+    /**
+     * 严格填充,只针对非主键的字段,只有该表注解了fill 并且 字段名和字段属性 能匹配到才会进行填充(null 值不填充)
      *
-     * @param metaObject meta object parameter
-     * @return TableInfo
+     * @param insertFill  是否验证在 insert 时填充
+     * @param tableInfo   cache 缓存
+     * @param metaObject  metaObject meta object parameter
+     * @param strictFills 填充信息
+     * @return this
      * @since 3.2.1
      */
-    default TableInfo findTableInfo(MetaObject metaObject) {
-        return metaObject.hasGetter(Constants.MP_OPTLOCK_ET_ORIGINAL) ?
-            TableInfoHelper.getTableInfo(metaObject.getValue(Constants.MP_OPTLOCK_ET_ORIGINAL).getClass())
-            : TableInfoHelper.getTableInfo(metaObject.getOriginalObject().getClass());
+    default MetaObjectHandler strictFill(boolean insertFill, TableInfo tableInfo, MetaObject metaObject, List<StrictFill> strictFills) {
+        if (tableInfo != null && ((insertFill && tableInfo.isWithInsertFill()) || (!insertFill && tableInfo.isWithUpdateFill()))) {
+            List<TableFieldInfo> list = tableInfo.getFieldList();
+            strictFills.forEach(i -> {
+                final String fieldName = i.getFieldName();
+                Optional<TableFieldInfo> info = list.stream().filter(j -> j.getProperty().equals(fieldName) &&
+                    i.getFieldType().equals(j.getPropertyType()) &&
+                    ((insertFill && j.isWithInsertFill()) || (!insertFill && j.isWithUpdateFill())))
+                    .findFirst();
+                info.ifPresent(j -> strictFillStrategy(metaObject, fieldName, i.getFieldVal()));
+            });
+        }
+        return this;
     }
 
     /**
-     * 填充判断
-     * <li> 如果是主键,不填充 </li>
-     * <li> 根据字段名找不到字段,不填充 </li>
-     * <li> 字段类型与填充值类型不匹配,不填充 </li>
-     * <li> 字段类型需在TableField注解里配置fill: @TableField(value="test_type", fill = FieldFill.INSERT), 没有配置或者不匹配时不填充 </li>
-     * v_3.1.0以后的版本(不包括3.1.0),子类的值也可以自动填充,Timestamp的值也可以填入到java.util.Date类型里面
+     * 严格填充策略,默认有值不覆盖
      *
+     * @param metaObject metaObject meta object parameter
      * @param fieldName  java bean property name
-     * @param fieldVal   java bean property value
-     * @param metaObject meta object parameter
-     * @param fieldFill  填充策略枚举
-     * @return 是否进行填充
-     * @since 3.0.7
+     * @param fieldVal   java bean property value of Supplier
+     * @since 3.2.1
      */
-    default boolean isFill(String fieldName, Object fieldVal, MetaObject metaObject, FieldFill fieldFill) {
-        TableInfo tableInfo = findTableInfo(metaObject);
-        if (Objects.nonNull(tableInfo)) {
-            Optional<TableFieldInfo> first = tableInfo.getFieldList().stream()
-                //v_3.1.1+ 设置子类的值也可以通过
-                .filter(e -> e.getProperty().equals(fieldName) && e.getPropertyType().isAssignableFrom(fieldVal.getClass()))
-                .findFirst();
-            if (first.isPresent()) {
-                FieldFill fill = first.get().getFieldFill();
-                return fill.equals(fieldFill) || FieldFill.INSERT_UPDATE.equals(fill);
-            }
+    default void strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<Object> fieldVal) {
+        if (getFieldValByName(fieldName, metaObject) == null) {
+            setFieldValByName(fieldName, fieldVal.get(), metaObject);
         }
-        return false;
     }
 }

+ 69 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/StrictFill.java

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.core.handlers;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+
+import java.util.function.Supplier;
+
+/**
+ * 严格填充模式 model
+ *
+ * @author miemie
+ * @since 2019-11-26
+ */
+@Data
+@AllArgsConstructor
+public class StrictFill {
+    /**
+     * 字段名
+     */
+    private String fieldName;
+    /**
+     * 字段类型
+     */
+    private Class<?> fieldType;
+    /**
+     * 字段值
+     */
+    private Object fieldVal;
+    /**
+     * 获取字段值的函数
+     */
+    @Getter(AccessLevel.NONE)
+    private Supplier<Object> fieldValSupplier;
+
+    public static StrictFill of(String fieldName, Class<?> fieldType, Object fieldVal) {
+        return new StrictFill(fieldName, fieldType, fieldVal, null);
+    }
+
+    public static StrictFill of(String fieldName, Class<?> fieldType, Supplier<Object> fieldValSupplier) {
+        return new StrictFill(fieldName, fieldType, null, fieldValSupplier);
+    }
+
+    Supplier<Object> getFieldVal() {
+        if (fieldVal != null) {
+            return () -> fieldVal;
+        }
+        if (fieldValSupplier != null) {
+            return fieldValSupplier;
+        }
+        return () -> null;
+    }
+}

+ 22 - 4
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableFieldInfo.java

@@ -109,8 +109,23 @@ public class TableFieldInfo implements Constants {
     private String condition = SqlCondition.EQUAL;
     /**
      * 字段填充策略
+     *
+     * @deprecated 3.2.1
      */
+    @Deprecated
     private FieldFill fieldFill = FieldFill.DEFAULT;
+    /**
+     * 表字段是否启用了插入填充
+     *
+     * @since 3.2.1
+     */
+    private boolean withInsertFill;
+    /**
+     * 表字段是否启用了更新填充
+     *
+     * @since 3.2.1
+     */
+    private boolean withUpdateFill;
     /**
      * 缓存 sql select
      */
@@ -138,7 +153,10 @@ public class TableFieldInfo implements Constants {
         this.property = field.getName();
         this.propertyType = field.getType();
         this.isCharSequence = StringUtils.isCharSequence(this.propertyType);
-        this.fieldFill = tableField.fill();
+        final FieldFill fill = tableField.fill();
+        this.fieldFill = fill;
+        this.withInsertFill = fill == FieldFill.INSERT || fill == FieldFill.INSERT_UPDATE;
+        this.withUpdateFill = fill == FieldFill.UPDATE || fill == FieldFill.INSERT_UPDATE;
         this.update = tableField.update();
         JdbcType jdbcType = tableField.jdbcType();
         final Class<? extends TypeHandler> typeHandler = tableField.typeHandler();
@@ -323,7 +341,7 @@ public class TableFieldInfo implements Constants {
      */
     public String getInsertSqlPropertyMaybeIf(final String prefix) {
         String sqlScript = getInsertSqlProperty(prefix);
-        if (fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) {
+        if (withInsertFill) {
             return sqlScript;
         }
         return convertIf(sqlScript, property, insertStrategy);
@@ -353,7 +371,7 @@ public class TableFieldInfo implements Constants {
      */
     public String getInsertSqlColumnMaybeIf() {
         final String sqlScript = getInsertSqlColumn();
-        if (fieldFill == FieldFill.INSERT || fieldFill == FieldFill.INSERT_UPDATE) {
+        if (withInsertFill) {
             return sqlScript;
         }
         return convertIf(sqlScript, property, insertStrategy);
@@ -389,7 +407,7 @@ public class TableFieldInfo implements Constants {
         if (ignoreIf) {
             return sqlSet;
         }
-        if (fieldFill == FieldFill.UPDATE || fieldFill == FieldFill.INSERT_UPDATE) {
+        if (withUpdateFill) {
             // 不进行 if 包裹
             return sqlSet;
         }

+ 6 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfo.java

@@ -15,7 +15,6 @@
  */
 package com.baomidou.mybatisplus.core.metadata;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
@@ -131,12 +130,16 @@ public class TableInfo implements Constants {
     private String sqlSelect;
     /**
      * 表字段是否启用了插入填充
+     *
+     * @since 3.2.1
      */
     @Getter
     @Setter(AccessLevel.NONE)
     private boolean withInsertFill;
     /**
      * 表字段是否启用了更新填充
+     *
+     * @since 3.2.1
      */
     @Getter
     @Setter(AccessLevel.NONE)
@@ -394,7 +397,7 @@ public class TableInfo implements Constants {
     void setFieldList(List<TableFieldInfo> fieldList) {
         this.fieldList = fieldList;
         this.logicDelete = fieldList.parallelStream().anyMatch(TableFieldInfo::isLogicDelete);
-        this.withInsertFill = fieldList.parallelStream().anyMatch(i -> i.getFieldFill() == FieldFill.INSERT || i.getFieldFill() == FieldFill.INSERT_UPDATE);
-        this.withUpdateFill = fieldList.parallelStream().anyMatch(i -> i.getFieldFill() == FieldFill.UPDATE || i.getFieldFill() == FieldFill.INSERT_UPDATE);
+        this.withInsertFill = fieldList.parallelStream().anyMatch(TableFieldInfo::isWithInsertFill);
+        this.withUpdateFill = fieldList.parallelStream().anyMatch(TableFieldInfo::isWithUpdateFill);
     }
 }

+ 1 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/injector/methods/additional/LogicDeleteByIdWithFill.java

@@ -15,7 +15,6 @@
  */
 package com.baomidou.mybatisplus.extension.injector.methods.additional;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.core.enums.SqlMethod;
 import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
@@ -50,7 +49,7 @@ public class LogicDeleteByIdWithFill extends AbstractMethod {
         SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID;
         if (tableInfo.isLogicDelete()) {
             List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream()
-                .filter(i -> i.getFieldFill() == FieldFill.UPDATE || i.getFieldFill() == FieldFill.INSERT_UPDATE)
+                .filter(TableFieldInfo::isWithUpdateFill)
                 .collect(toList());
             if (CollectionUtils.isNotEmpty(fieldInfos)) {
                 String sqlSet = "SET " + fieldInfos.stream().map(i -> i.getSqlSet(EMPTY)).collect(joining(EMPTY))