mybatisPlus 更新数据为null时不生效

问题

User user = getUser();
user.setName(null);
userMapper.updateById(user)

执行代码后发现数据没有被置空。
原因:
MyBatis-Plus在更新时忽略null值,是其字段更新策略(FieldStrategy) 机制的设计行为:默认情况下,MyBatis-Plus会忽略更新值为null的字段,只更新非null字段

方案详解与示例

1. 字段注解(推荐用于特定字段)

如果只是实体类中的少数几个字段需要支持空值更新,这是最直接和推荐的方式。

java

public class User {
    @TableId(value = "id")
    private Long id;
    private String name;
    
    // 关键注解:使此字段在更新时即使为null也会被加入SQL
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private String email;
}

之后,你使用updateById方法时,email字段即使为null也会被更新到数据库。
也可以使用一下注入方法
在可能为空的Model类字段上方加@TableField(fill = FieldFill.INSERT_UPDATE)

public class User {
    @TableId(value = "id")
    private Long id;
    private String name;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String email;
}

注意:在较新版本的MyBatis-Plus中,FieldStrategy.IGNORED已被标记为@Deprecated。官方推荐使用FieldStrategy.ALWAYS来代替。

java

@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String email;

2. 使用UpdateWrapper(最安全灵活)

这是最安全、对代码侵入性最小的方式,特别适合在服务层逻辑中动态处理。

java

@Autowired
private UserService userService;

public void updateUserEmailToNull(Long userId) {
    // 创建UpdateWrapper,构建更新条件
    LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
    // 设置需要更新的字段为null,并指定更新条件
    wrapper.set(User::getEmail, null)
           .eq(User::getId, userId);
    
    // 执行更新,传入的实体对象可以为null或空对象
    userService.update(null, wrapper);
}

这种方式完全绕开了实体类的字段策略,直接生成SQL,精准地将指定字段更新为null。

3. 全局配置(请谨慎使用)

在你的application.yml配置文件中进行如下修改:

mybatis-plus:
  global-config:
    db-config:
      update-strategy: ignored  # 旧版本中可能叫 field-strategy: 0

强烈不推荐此方法,因为它会导致所有实体的所有字段在更新时都会忽略null判断。这意味着,如果你在更新时不小心漏掉了某个字段的值,该字段就很可能被意外地更新为null,从而造成数据丢失

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐