MyBatis-Plus updateById 无法更新 null 值字段
问题笔记:MyBatis-Plus updateById 无法更新 null 值字段
问题现象
使用 updateById 方法时,即使显式设置 entity.setPayDate(null),数据库中的 pay_date 字段仍未被更新为 NULL。
根本原因
MyBatis-Plus 默认策略
默认字段更新策略为 FieldStrategy.NOT_NULL,会忽略值为 null 的字段。
BeanUtils 拷贝问题
工具类(如 BeanUtil.toBean)可能忽略 null 值字段的拷贝。
数据库约束
表字段可能有默认值或 NOT NULL 约束。
解决方案
- 字段注解强制更新(推荐)
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Date payDate;
效果:强制更新该字段,即使为 null。
适用场景:明确需要更新 null 的字段。
- 使用 UpdateWrapper 显式更新
UpdateWrapper<Entity> wrapper = new UpdateWrapper<>();
wrapper.eq("id", entity.getId())
.set("pay_date", null); // 显式设置null
baseMapper.update(null, wrapper);
优势:精准控制,不依赖实体类配置。
- 全局配置(慎用)
yaml
mybatis-plus:
global-config:
db-config:
update-strategy: ignored
风险:影响所有实体类的更新行为。
验证步骤
检查生成的 SQL
开启日志 logging.level.org.apache.ibatis=DEBUG,确认 SQL 是否包含 pay_date=null。
调试实体对象
在 updateById 前断点检查 entity.getPayDate() 是否为 null。
数据库检查
直接查询表结构:SHOW CREATE TABLE your_table,确认无默认值约束。
注意事项
乐观锁字段:若使用 @Version,需确保版本号已更新。
性能影响:全字段更新可能增加不必要的数据库操作。
事务管理:建议添加 @Transactional 保证操作原子性。
总结
方案 侵入性 适用场景
字段注解 IGNORED 低 明确需更新 null 的字段
UpdateWrapper 无 动态控制更新字段
全局配置 高 全表字段需更新 null
推荐优先级:字段注解 > UpdateWrapper > 全局配置。