MyBatis-Plus 更新字段为 null 不生效?updateStrategy
一定要搞懂!
💡 前言
大家在开发中肯定遇到过这样的场景:想把某个字段清空,比如“处理人”或“处理时间”,明明代码里写了 setDealTime(null),但数据库里的值却纹丝不动。
今天我就来分享我的踩坑经验,教你如何正确地把字段更新为 null,别再被 MyBatis-Plus 的默认策略坑了!
🐞 问题现场
举个真实例子,我在做工单系统,有个字段:
/**
* 处理时间
*/
private Date dealTime;
数据库定义:
deal_time datetime DEFAULT NULL COMMENT '处理时间'
需求很简单:把这个字段清空。
于是写了这么一段代码:
Issue byId = issueService.getById(id);
byId.setDealTime(null);
issueService.updateById(byId);
结果:数据库里的 deal_time
还是之前的时间,并没有被清空!
🔍 查了 SQL 才明白
打开 SQL 日志一看:
UPDATE itsm_issue
SET issue_code = ?,
update_user = ?,
update_time = ?
WHERE id = ? AND is_deleted = 0
你看到了吗?deal_time
根本没出现在 SET
中!
原因就是 MyBatis-Plus 默认策略:
- FieldStrategy.NOT_NULL
- 也就是说:只有非
null
的字段才会参与更新 - 所以当你
setDealTime(null)
时,它就直接跳过了这个字段
✅ 解决办法
方案 1:给字段加注解(推荐)
最直接的办法是在实体类字段上加一个注解,告诉 MyBatis-Plus:
不管值是不是 null,都参与更新
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
@TableField(value = "deal_time", updateStrategy = FieldStrategy.ALWAYS)
private Date dealTime;
- ALWAYS:任何时候都更新,包括 null
- 再执行
setDealTime(null)
+updateById()
- 生成的 SQL 会是:
UPDATE itsm_issue
SET deal_time = ?
WHERE id = ?
-- 参数: null
✅ 这样字段就真正清空了。
方案 2:直接用 UpdateWrapper 显式设置
如果你不想动实体类,也可以用 UpdateWrapper
:
UpdateWrapper<Issue> wrapper = new UpdateWrapper<>();
wrapper.eq("id", id)
.set("deal_time", null); // 显式置空
issueMapper.update(null, wrapper);
- 不依赖实体对象
- SQL 直接生成
SET deal_time = NULL
- 简单粗暴,有效 ✅
⚠️ 其他坑点
-
自动填充(MetaObjectHandler)
- 如果你配置了更新自动填充:
@Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "dealTime", Date.class, new Date()); }
- 即使你设置了
null
,也会被填成当前时间 - 解决:加判断
if (getFieldValByName("dealTime", metaObject) == null) { setFieldValByName("dealTime", new Date(), metaObject); }
-
前端传参问题
- 比如
el-date-picker
默认绑定当前时间 - 建议通过浏览器 Network 面板确认请求体,确保传递的是你想要的值
- 比如
📌 小结
问题 | 原因 | 解决方案 |
---|---|---|
setXxx(null) 不生效 | 默认策略忽略 null | 给字段加 @TableField(updateStrategy = ALWAYS) |
SQL 中字段没出现 | 字段被过滤 | 检查策略,或用 UpdateWrapper 显式设置 |
值被自动填充 | MetaObjectHandler 自动填充逻辑 | 添加 null 判断 |
小建议:
- 对于“清空”字段(处理人、处理时间等),默认加上
ALWAYS
- 自动填充逻辑谨慎,避免覆盖业务主动设置的
null
- 开启 SQL 日志,是排查这类问题最有效的方法