saveOrUpdate 有个缺点,不会把值赋值为null,解决办法

针对 MyBatis-Plus 的 saveOrUpdate 方法无法将字段更新为 null 的问题,这是因为 MyBatis-Plus 默认会忽略 null 值字段。以下是几种解决方案:

方案 1:使用 update(entity, wrapper) 手动指定更新条件

原理 :通过 UpdateWrapper 明确指定需要更新为 null 的字段。

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    public void updateWithNullValue() {
        User user = new User();
        user.setId(1L);
        user.setUsername(null); // 需要更新为 null 的字段

        // 手动构建 UpdateWrapper,强制更新 null 值字段
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.set("username", null) // 指定 username 字段更新为 null
               .eq("id", user.getId()); // 更新条件:ID = 1

        // 调用 update 方法,第一个参数可以为 null(因为条件已在 wrapper 中)
        boolean success = this.update(null, wrapper);
        if (success) {
            System.out.println("更新 null 值成功");
        }
    }
}

方案 2:配置全局字段策略(推荐)

原理 :通过配置 FieldStrategy 让 MyBatis-Plus 不忽略 null 值。

方式 1:配置文件(application.yml)
yaml 复制代码
mybatis-plus:
  global-config:
    db-config:
      update-strategy: IGNORED  # 更新策略:忽略判断,所有字段都更新(包括 null)
方式 2:Java 配置类
java 复制代码
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 其他配置...
        
        // 配置全局策略
        GlobalConfig globalConfig = new GlobalConfig();
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        dbConfig.setUpdateStrategy(FieldStrategy.IGNORED); // 更新时忽略字段非空判断
        globalConfig.setDbConfig(dbConfig);
        
        return interceptor;
    }
}

方案 3:使用 @TableField 注解(细粒度控制)

原理 :在实体类字段上指定更新策略为 IGNORED

java 复制代码
@Data
@TableName("t_user")
public class User {
    @TableId
    private Long id;
    
    @TableField(updateStrategy = FieldStrategy.IGNORED) // 该字段更新时忽略 null 判断
    private String username;
    
    private String phone;
    
    @TableField(updateStrategy = FieldStrategy.IGNORED) // 该字段更新时忽略 null 判断
    private Integer age;
}

方案 4:自定义 SQL 方法

原理 :在 Mapper 接口中自定义更新方法,使用 @Update 注解编写 SQL。

java 复制代码
public interface UserMapper extends BaseMapper<User> {

    @Update("UPDATE t_user SET username = #{username}, age = #{age} WHERE id = #{id}")
    boolean updateWithNull(@Param("id") Long id, 
                          @Param("username") String username, 
                          @Param("age") Integer age);
}

Service 层调用

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    public void customUpdateWithNull() {
        boolean success = baseMapper.updateWithNull(1L, null, 25);
        if (success) {
            System.out.println("自定义 SQL 更新 null 值成功");
        }
    }
}

总结

方案 优点 缺点 适用场景
方案 1 灵活,按需更新 代码冗余 少量需要更新 null 的场景
方案 2 全局生效,无需修改代码 影响所有实体 项目中大量需要更新 null
方案 3 细粒度控制,不影响其他字段 需修改实体类 部分字段需要更新 null
方案 4 完全自定义 SQL 维护成本高 复杂更新逻辑或性能敏感场景

推荐顺序:方案 3(细粒度控制)→ 方案 2(全局配置)→ 方案 1(临时需求)→ 方案 4(特殊场景)。

相关推荐
xiaopengbc几秒前
在 Python 中实现观察者模式的具体步骤是什么?
开发语言·python·观察者模式
刘婉晴2 分钟前
【Java】NIO 简单介绍
java·nio
Python大数据分析@6 分钟前
python用selenium怎么规避检测?
开发语言·python·selenium·网络爬虫
ThreeAu.9 分钟前
Miniconda3搭建Selenium的python虚拟环境全攻略
开发语言·python·selenium·minicoda·python环境配置
渣哥20 分钟前
聊聊我和 ArrayList、LinkedList、Vector 的“一地鸡毛”
java
浮游本尊23 分钟前
Java学习第20天 - 性能优化与监控
java
zhangfeng113327 分钟前
R 语法高亮为什么没有,是需要安装专用的编辑软件,R语言自带的R-gui 功能还是比较简单
开发语言·r语言
纪莫1 小时前
技术面:Java并发(线程同步、死锁、多线程编排)
java·java面试⑧股
衍余未了1 小时前
k8s 内置的containerd配置阿里云个人镜像地址及认证
java·阿里云·kubernetes