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 约束。

解决方案

  1. 字段注解强制更新(推荐)
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Date payDate;

效果:强制更新该字段,即使为 null。

适用场景:明确需要更新 null 的字段。

  1. 使用 UpdateWrapper 显式更新
UpdateWrapper<Entity> wrapper = new UpdateWrapper<>();
wrapper.eq("id", entity.getId())
       .set("pay_date", null); // 显式设置null
baseMapper.update(null, wrapper);

优势:精准控制,不依赖实体类配置。

  1. 全局配置(慎用)
    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 > 全局配置。