当前使用版本(必填,否则不予处理)
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)