当前使用版本(必填,否则不予处理)

v3.4.1

该问题是如何引起的?(确定最新版也有问题再提!!!)

重现步骤(如果有就写完整)

表字段,在更新的时候自动设置更新人id

    /**
     * 更新人ID
     */
    @TableField(value = "updated_uid", fill = FieldFill.UPDATE)
    private Long updatedUid;

自定义实现自动填充,见updateFill方法,设置更新人id

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.debug("创建自动填充");
        this.strictInsertFill(metaObject, "createdAt", Long.class, DateUtils.getNowSecond());
        this.strictInsertFill(metaObject, "updatedAt", Long.class, DateUtils.getNowSecond());
        this.strictInsertFill(metaObject, "createdUid", Long.class, getUserId());
        this.strictInsertFill(metaObject, "isDel", Integer.class, 0);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.debug("修改自动填充");
        metaObject.setValue("updatedAt", DateUtils.getNowSecond());
        this.strictUpdateFill(metaObject, "updatedUid", Long.class, getUserId() == 0L ? null : getUserId());
    }

    /**
     * 获取用户id
     *
     * @return java.lang.Long
     */
    private Long getUserId() {
        return Optional.ofNullable(UserSessionHolder.getInstance().getUser())
                .map(AuthUser::getDlabUserId).orElse(0L);
    }
}

源码注释:如果提供的值为null也不填充


    /**
     * 严格模式填充策略,默认有值不覆盖,如果提供的值为null也不填充
     *
     * @param metaObject metaObject meta object parameter
     * @param fieldName  java bean property name
     * @param fieldVal   java bean property value of Supplier
     * @return this
     * @since 3.3.0
     */
    default MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {
        if (metaObject.getValue(fieldName) == null) {
            Object obj = fieldVal.get();
            if (Objects.nonNull(obj)) {
                metaObject.setValue(fieldName, obj);
            }
        }
        return this;
    }

报错信息

但是,当设置的值为null的时候还是会进行填充

==>  Preparing: UPDATE item_detail SET base_detail=?, updated_at=?, updated_uid=? WHERE id=? AND is_del=0
==> Parameters: ERP商品006(String), 1663661182(Long), null, 10779(Long)
<==    Updates: 1

Comment From: miemieYaho

你debug有看到metaObject.setValue(fieldName, obj);这里的obj为null吗?

Comment From: wenlincheng

你debug有看到metaObject.setValue(fieldName, obj);这里的obj为null吗?

为null的,跳过了这个逻辑,但是拼出来的sql还是会设置null

Comment From: wenlincheng

你debug有看到metaObject.setValue(fieldName, obj);这里的obj为null吗?

想设置 updateStrategy = FieldStrategy.NOT_NULL 跳过null也没法实现,调试发现设置了 fill = FieldFill.UPDATE ,updateStrategy 就不会生效,源码如下: com/baomidou/mybatisplus/core/metadata/TableFieldInfo.java:431

        if (withUpdateFill) {
            // 不进行 if 包裹
            return sqlSet;
        }
        return convertIf(sqlSet, convertIfProperty(newPrefix, property), updateStrategy);

Comment From: miemieYaho

设置了自动填充则不进行任何if包裹,必须有值

Comment From: wenlincheng

设置了自动填充则不进行任何if包裹,必须有值

设置了自动填充,怎么实现为null就不更新之前的值呢

Comment From: miemieYaho

??????,我就问你,

if (metaObject.getValue(fieldName) == null) {
            Object obj = fieldVal.get();
            if (Objects.nonNull(obj)) {
                metaObject.setValue(fieldName, obj); // 这段代码执行时,obj到底是不是null吧?
            }
        }
        return this;

Comment From: wenlincheng

??????,我就问你,

java if (metaObject.getValue(fieldName) == null) { Object obj = fieldVal.get(); if (Objects.nonNull(obj)) { metaObject.setValue(fieldName, obj); // 这段代码执行时,obj到底是不是null吧? } } return this;

obj是null,但是拼出来的sql还是会设置字段=null

Comment From: miemieYaho

metaObject.setValue(fieldName, obj); 这段代码执行了没有?

Comment From: wenlincheng

metaObject.setValue(fieldName, obj); 这段代码执行了没有?

没有

Comment From: miemieYaho

那不就得了,说明你entity的字段本身就是null

Comment From: wenlincheng

Comment From: wenlincheng

那不就得了,说明你entity的字段本身就是null

你还没理解到我说的问题,为null为啥还要更新数据库呢,设置updateStrategy = FieldStrategy.NOT_NULL 也仍然会更新为null

Comment From: valarchie

我也发现了这个问题... 如果设置了 FieldStrategy.NOT_NULL , 直觉上看 如果我传的值是null, update的sql, 就不应该把这个字段拼进去

Comment From: valarchie

那不就得了,说明你entity的字段本身就是null

你还没理解到我说的问题,为null为啥还要更新数据库呢,设置updateStrategy = FieldStrategy.NOT_NULL 也仍然会更新为null

我get到点了。。 注释当中的 如果提供的值为null也不填充。 ——》 不填充的是我们操作的那个实体。。 我以为是指数据库的记录。。

Comment From: someok

我觉得这地方的处理应该调整为,update 的时候,应该直接忽略掉 FieldFill.INSERT 的字段,而不该用 null 填充

Comment From: gaspire

我也遇到类似问题,有解决办法吗?

Comment From: someok

我也遇到类似问题,有解决办法吗?

可以配合 updateStrategy = FieldStrategy.NEVER 使用:

@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER)